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 | |
---|
37 | FILE_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 | |
---|
57 | bootsector: |
---|
58 | jmp $BOOTSEG, $1f /* reload cs:ip to match relocation addr */ |
---|
59 | 1: |
---|
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 */ |
---|
77 | prloop: |
---|
78 | lodsb |
---|
79 | int $0x10 |
---|
80 | loop prloop |
---|
81 | freeze: jmp freeze |
---|
82 | |
---|
83 | why: .ascii "This image cannot be loaded from a floppy disk.\r\n" |
---|
84 | why_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 |
---|
92 | setup_sects: |
---|
93 | .byte SETUPSECS |
---|
94 | root_flags: |
---|
95 | .word 0 |
---|
96 | syssize: |
---|
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 | |
---|
106 | ram_size: |
---|
107 | .word 0 |
---|
108 | vid_mode: |
---|
109 | .word 0 |
---|
110 | root_dev: |
---|
111 | .word 0 |
---|
112 | boot_flag: |
---|
113 | .word 0xAA55 |
---|
114 | jump: |
---|
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 |
---|
119 | header: |
---|
120 | .byte 'H', 'd', 'r', 'S' |
---|
121 | version: |
---|
122 | .word 0x0207 /* 2.07 */ |
---|
123 | realmode_swtch: |
---|
124 | .long 0 |
---|
125 | start_sys: |
---|
126 | .word 0 |
---|
127 | kernel_version: |
---|
128 | .word 0 |
---|
129 | type_of_loader: |
---|
130 | .byte 0 |
---|
131 | loadflags: |
---|
132 | .byte 0 |
---|
133 | setup_move_size: |
---|
134 | .word 0 |
---|
135 | code32_start: |
---|
136 | .long 0 |
---|
137 | ramdisk_image: |
---|
138 | .long 0 |
---|
139 | ramdisk_size: |
---|
140 | .long 0 |
---|
141 | bootsect_kludge: |
---|
142 | .long 0 |
---|
143 | heap_end_ptr: |
---|
144 | .word 0 |
---|
145 | pad1: |
---|
146 | .word 0 |
---|
147 | cmd_line_ptr: |
---|
148 | .long 0 |
---|
149 | initrd_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 |
---|
154 | kernel_alignment: |
---|
155 | .long 0 |
---|
156 | relocatable_kernel: |
---|
157 | .byte 0 |
---|
158 | pad2: |
---|
159 | .byte 0, 0, 0 |
---|
160 | cmdline_size: |
---|
161 | .long 0 |
---|
162 | hardware_subarch: |
---|
163 | .long 0 |
---|
164 | hardware_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 | */ |
---|
174 | setup_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 | */ |
---|
188 | run_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 |
---|
206 | 1: |
---|
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 |
---|