593b5d86c7963e525189b81884dbdf9634ac7f8c
[people/dverkamp/gpxe.git] / src / arch / i386 / prefix / romprefix.S
1 /* At entry, the processor is in 16 bit real mode and the code is being
2  * executed from an address it was not linked to. Code must be pic and
3  * 32 bit sensitive until things are fixed up.
4  *
5  * Also be very careful as the stack is at the rear end of the interrupt
6  * table so using a noticeable amount of stack space is a no-no.
7  */
8
9         .text
10         .code16
11         .arch i386
12         .section ".prefix", "ax", @progbits
13         
14         .org    0x00
15 romheader:
16         .word   0xAA55                  /* BIOS extension signature */
17 romheader_size: .byte _load_size_sect   /* Size in 512-byte blocks */
18         jmp     init_vector             /* Initialisation vector */
19         .org    0x16
20         .word   undiheader
21         .org    0x18
22         .word   pciheader
23         .org    0x1a
24         .word   pnpheader
25         .size romheader, . - romheader
26         
27         .section ".zinfo.fixup", "a"    /* Compressor fixup information */
28         .ascii  "SUBB"
29         .long   romheader_size
30         .long   512
31         .long   0
32         .previous
33
34 pciheader:
35         .ascii  "PCIR"                  /* Signature */
36         .word   pci_vendor_id           /* Vendor ID */ 
37         .word   pci_device_id           /* Device ID */
38         .word   0x0000                  /* pointer to vital product data */
39         .word   pciheader_len           /* PCI data structure length */
40         .byte   0x00                    /* PCI data structure revision */
41         .byte   0x02                    /* Device Base Type code */
42         .byte   0x00                    /* Device Sub-Type code */
43         .byte   0x00                    /* Device Interface Type code */
44 pciheader_size: .word _load_size_sect   /* Image length same as offset 02h */
45         .word   0x0001                  /* revision level of code/data */
46         .byte   0x00                    /* code type */
47         .byte   0x80                    /* Flags (last PCI data structure) */
48         .word   0x0000                  /* reserved */
49         .equ pciheader_len, . - pciheader
50         .size pciheader, . - pciheader
51         
52         .section ".zinfo.fixup", "a"    /* Compressor fixup information */
53         .ascii  "SUBW"
54         .long   pciheader_size
55         .long   512
56         .long   0
57         .previous
58
59 pnpheader:
60         .ascii  "$PnP"                  /* Signature */
61         .byte   0x01                    /* Structure revision */
62         .byte   ( pnpheader_len / 16 )  /* Length (in 16 byte increments) */
63         .word   0x0000                  /* Offset of next header */
64         .byte   0x00                    /* Reserved */
65         .byte   0x00                    /* Checksum */
66         .long   0x00000000              /* Device identifier */
67         .word   mfgstr                  /* Manufacturer string */
68         .word   prodstr                 /* Product name */
69         .byte   0x02                    /* Device base type code */
70         .byte   0x00                    /* Device sub-type code */
71         .byte   0x00                    /* Device interface type code */
72         .byte   0x54                    /* Device indicator */
73         .word   0x0000                  /* Boot connection vector */
74         .word   0x0000                  /* Disconnect vector */
75         .word   exec_vector             /* Boot execution vector */
76         .word   0x0000                  /* Reserved */
77         .word   0x0000                  /* Static resource information vector*/
78         .equ pnpheader_len, . - pnpheader
79         .size pnpheader, . - pnpheader
80
81 mfgstr:
82         .asciz  "http://etherboot.org"
83         .size mfgstr, . - mfgstr
84 prodstr:
85         .asciz  "Etherboot"
86         .size prodstr, . - prodstr
87         
88 undiheader:
89         .ascii  "UNDI"                  /* Signature */
90         .byte   undiheader_len          /* Length of structure */
91         .byte   0                       /* Checksum */
92         .byte   0                       /* Structure revision */
93         .byte   0,1,2                   /* PXE version: 2.1.0 */
94         .word   undiloader              /* Offset to loader routine */
95         .word   _data16_size            /* Stack segment size */
96         .word   _data16_size            /* Data segment size */
97         .word   _text16_size            /* Code segment size */
98         .equ undiheader_len, . - undiheader
99         .size undiheader, . - undiheader
100
101 /* Initialisation vector
102  *
103  * Determine whether or not this is a PnP system via a signature
104  * check.  If it is PnP, return to the PnP BIOS indicating that we are
105  * a boot-capable device; the BIOS will call our boot execution vector
106  * if it wants to boot us.  If it is not PnP, hook INT 19.
107  */
108 init_vector:
109         pushw   %si
110         cmpw    $'$'+'P'*256, %es:0(%di)
111         jne     notpnp
112         cmpw    $'n'+'P'*256, %es:2(%di)
113         jne     notpnp
114 ispnp:
115         movw    $ispnp_message, %si
116         jmp     99f
117 notpnp:
118         pushw   %ds
119         pushw   $0
120         popw    %ds
121         pushw   %cs
122         pushw   $exec_vector
123         popl    ( 0x19 * 4 )
124         popw    %ds
125         movw    $notpnp_message, %si
126 99:
127         call    print_message
128         movw    $0x20, %ax
129         popw    %si
130         lret
131         .size init_vector, . - init_vector
132
133 ispnp_message:
134         .asciz  "Etherboot detected PnP BIOS\r\n"
135         .size ispnp_message, . - ispnp_message
136 notpnp_message:
137         .asciz  "Etherboot detected non-PnP BIOS\r\n"
138         .size notpnp_message, . - notpnp_message
139
140 /* Boot execution vector
141  *pciheader_size
142  * Called by the PnP BIOS when it wants to boot us, or via the hooked
143  * INT 19 if we detected a non-PnP BIOS.
144  */     
145 exec_vector:
146         /* Obtain a reasonably-sized stack */
147         xorw    %ax, %ax
148         movw    %ax, %ss
149         movw    $0x7c00, %sp
150         
151         movw    $exec_message, %si
152         call    print_message
153
154         call    install
155
156         /* Set up real-mode stack */
157         movw    %bx, %ss
158         movw    $_estack16, %sp
159
160         /* Jump to .text16 segment */
161         pushw   %ax
162         pushw   $1f
163         lret
164         .section ".text16", "awx", @progbits
165 1:
166         pushl   $main
167         pushw   %cs
168         call    prot_call
169         popl    %eax /* discard */
170
171         /* Boot next device */
172         int     $0x18
173         .previous
174
175 exec_message:
176         .asciz  "Etherboot starting boot\r\n"
177         .size exec_message, . - exec_message
178
179 /* UNDI loader
180  *
181  * Called by an external program to load our PXE stack.
182  */
183 undiloader:
184         /* Save registers */
185         pushl   %edi
186         pushw   %es
187         pushw   %bx
188         /* UNDI loader parameter structure address into %es:%di */
189         movw    %sp, %bx
190         movw    %ss:12(%bx), %di
191         movw    %ss:14(%bx), %es
192         /* Install to specified real-mode addresses */
193         pushw   %di
194         movw    %es:12(%di), %bx
195         movw    %es:14(%di), %ax
196         call    install_prealloc
197         popw    %di
198         /* Call UNDI loader C code */
199         pushl   $pxe_loader_call
200         pushw   %cs
201         pushw   $1f
202         pushw   %ax
203         pushw   $prot_call
204         lret
205 1:      popw    %bx     /* discard */
206         popw    %bx     /* discard */
207         /* Restore registers and return */
208         popw    %bx
209         popw    %es
210         popl    %edi
211         lret
212         .size undiloader, . - undiloader
213                                 
214 /* Utility function: print string
215  */
216 print_message:
217         pushw   %ax
218         pushw   %bx
219         pushw   %bp
220         movw    $0x0007, %bx
221 1:      cs lodsb
222         testb   %al, %al
223         je      2f
224         movb    $0x0e, %ah              /* write char, tty mode */
225         int     $0x10
226         jmp     1b
227 2:      popw    %bp
228         popw    %bx
229         popw    %ax
230         ret
231         .size print_message, . - print_message