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