[zbin] Change fixup semantics to support ROMs over 128k uncompressed
[people/oremanj/gpxe.git] / src / arch / i386 / prefix / lkrnprefix.S
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