1/* 2 Copyright (C) 2000, Entity Cyber, Inc. 3 4 Authors: Gary Byers (gb@thinguin.org) 5 Marty Connor (mdc@thinguin.org) 6 7 This software may be used and distributed according to the terms 8 of the GNU Public License (GPL), incorporated herein by reference. 9 10 Description: 11 12 This is just a little bit of code and data that can get prepended 13 to a ROM image in order to allow bootloaders to load the result 14 as if it were a Linux kernel image. 15 16 A real Linux kernel image consists of a one-sector boot loader 17 (to load the image from a floppy disk), followed a few sectors 18 of setup code, followed by the kernel code itself. There's 19 a table in the first sector (starting at offset 497) that indicates 20 how many sectors of setup code follow the first sector and which 21 contains some other parameters that aren't interesting in this 22 case. 23 24 When a bootloader loads the sectors that comprise a kernel image, 25 it doesn't execute the code in the first sector (since that code 26 would try to load the image from a floppy disk.) The code in the 27 first sector below doesn't expect to get executed (and prints an 28 error message if it ever -is- executed.) 29 30 We don't require much in the way of setup code. Historically, the 31 Linux kernel required at least 4 sectors of setup code. 32 Therefore, at least 4 sectors must be present even though we don't 33 use them. 34 35*/ 36 37FILE_LICENCE ( GPL_ANY ) 38 39#define SETUPSECS 4 /* Minimal nr of setup-sectors */ 40#define PREFIXSIZE ((SETUPSECS+1)*512) 41#define PREFIXPGH (PREFIXSIZE / 16 ) 42#define BOOTSEG 0x07C0 /* original address of boot-sector */ 43#define INITSEG 0x9000 /* we move boot here - out of the way */ 44#define SETUPSEG 0x9020 /* setup starts here */ 45#define SYSSEG 0x1000 /* system loaded at 0x10000 (65536). */ 46 47 .text 48 .code16 49 .arch i386 50 .org 0 51 .section ".prefix", "ax", @progbits 52/* 53 This is a minimal boot sector. If anyone tries to execute it (e.g., if 54 a .lilo file is dd'ed to a floppy), print an error message. 55*/ 56 57bootsector: 58 jmp $BOOTSEG, $1f /* reload cs:ip to match relocation addr */ 591: 60 movw $0x2000, %di /* 0x2000 is arbitrary value >= length 61 of bootsect + room for stack */ 62 63 movw $BOOTSEG, %ax 64 movw %ax,%ds 65 movw %ax,%es 66 67 cli 68 movw %ax, %ss /* put stack at BOOTSEG:0x2000. */ 69 movw %di,%sp 70 sti 71 72 movw $why_end-why, %cx 73 movw $why, %si 74 75 movw $0x0007, %bx /* page 0, attribute 7 (normal) */ 76 movb $0x0e, %ah /* write char, tty mode */ 77prloop: 78 lodsb 79 int $0x10 80 loop prloop 81freeze: jmp freeze 82 83why: .ascii "This image cannot be loaded from a floppy disk.\r\n" 84why_end: 85 86 87/* 88 The following header is documented in the Linux source code at 89 Documentation/i386/boot.txt 90*/ 91 .org 497 92setup_sects: 93 .byte SETUPSECS 94root_flags: 95 .word 0 96syssize: 97 .long -PREFIXPGH 98 99 .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ 100 .ascii "ADDL" 101 .long syssize 102 .long 16 103 .long 0 104 .previous 105 106ram_size: 107 .word 0 108vid_mode: 109 .word 0 110root_dev: 111 .word 0 112boot_flag: 113 .word 0xAA55 114jump: 115 /* Manually specify a two-byte jmp instruction here rather 116 * than leaving it up to the assembler. */ 117 .byte 0xeb 118 .byte setup_code - header 119header: 120 .byte 'H', 'd', 'r', 'S' 121version: 122 .word 0x0207 /* 2.07 */ 123realmode_swtch: 124 .long 0 125start_sys: 126 .word 0 127kernel_version: 128 .word 0 129type_of_loader: 130 .byte 0 131loadflags: 132 .byte 0 133setup_move_size: 134 .word 0 135code32_start: 136 .long 0 137ramdisk_image: 138 .long 0 139ramdisk_size: 140 .long 0 141bootsect_kludge: 142 .long 0 143heap_end_ptr: 144 .word 0 145pad1: 146 .word 0 147cmd_line_ptr: 148 .long 0 149initrd_addr_max: 150 /* We don't use an initrd but some bootloaders (e.g. SYSLINUX) have 151 * been known to require this field. Set the value to 2 GB. This 152 * value is also used by the Linux kernel. */ 153 .long 0x7fffffff 154kernel_alignment: 155 .long 0 156relocatable_kernel: 157 .byte 0 158pad2: 159 .byte 0, 0, 0 160cmdline_size: 161 .long 0 162hardware_subarch: 163 .long 0 164hardware_subarch_data: 165 .byte 0, 0, 0, 0, 0, 0, 0, 0 166 167/* 168 We don't need to do too much setup. 169 170 This code gets loaded at SETUPSEG:0. It wants to start 171 executing the image that's loaded at SYSSEG:0 and 172 whose entry point is SYSSEG:0. 173*/ 174setup_code: 175 /* We expect to be contiguous in memory once loaded. The Linux image 176 * boot process requires that setup code is loaded separately from 177 * "non-real code". Since we don't need any information that's left 178 * in the prefix, it doesn't matter: we just have to ensure that 179 * %cs:0000 is where the start of the image *would* be. 180 */ 181 ljmp $(SYSSEG-(PREFIXSIZE/16)), $run_gpxe 182 183 184 .org PREFIXSIZE 185/* 186 We're now at the beginning of the kernel proper. 187 */ 188run_gpxe: 189 /* Set up stack just below 0x7c00 */ 190 xorw %ax, %ax 191 movw %ax, %ss 192 movw $0x7c00, %sp 193 194 /* Install gPXE */ 195 call install 196 197 /* Set up real-mode stack */ 198 movw %bx, %ss 199 movw $_estack16, %sp 200 201 /* Jump to .text16 segment */ 202 pushw %ax 203 pushw $1f 204 lret 205 .section ".text16", "awx", @progbits 2061: 207 pushl $main 208 pushw %cs 209 call prot_call 210 popl %ecx /* discard */ 211 212 /* Uninstall gPXE */ 213 call uninstall 214 215 /* Boot next device */ 216 int $0x18 217