1 /* $NetBSD: start_rom.S,v 1.1.4.3 2004/09/21 13:17:18 skrll Exp $ */
5 * mostly from freebsd:sys/arch/i396/boot/netboot/start2.S
8 #include <machine/asm.h>
9 #define addr32 .byte 0x67
14 #define BOOTSTACK 0xfffc
22 /* At entry, the processor is in 16 bit real mode and the code is being
23 * executed from an address it was not linked to. Code must be pic and
24 * 32 bit sensitive until things are fixed up.
26 .word 0xaa55 /* bios extension signature */
27 .byte 0 /* no. of 512B blocks - set by genprom */
28 jmp 1f /* enter from bios here */
29 .byte 0 /* checksum */
31 . = 0x18 /* required offset of pointer */
32 .word (pcidata - textstart)
37 .word 0 /* pointer to vital product data */
38 .word (pcidataend - pcidata)
39 .long (0 + (PCI_CLASS << 8)) /* class, revision */
40 .word 0 /* no. of 512B blocks - set by genprom */
41 .word 0 /* revision */
42 .byte 0 /* code type */
43 .byte 0x80 /* "indicator" - last image */
44 .word 0 /* reserved */
55 cmp $0x4d52, %ax /* $0x4d52 == 'MR' */
56 jz 2f /* we have been here - don't clobber saved vector */
58 /* save old INT19 vector to a secret location (???) */
64 /* set INT19 vector to our entry */
65 movl $(_C_LABEL(start)-reloc), %eax
70 /* set a signature (is this a safe location?) */
71 movw $0x4d52, %ax /* 0x4d52 == 'MR' */
84 movw $(imesg-textstart), %si
94 imesg: .asciz "bsd rom installed\r\n"
95 cmesg: .asciz "bsd rom called\r\n"
96 rmesg: .asciz "bsd rom relocated\r\n"
97 emesg: .asciz "bsd rom done\r\n"
100 * message: write the message in %ds:%esi to console
109 lodsb /* load a byte into %al */
120 movb $0x00, %ah /* wait for keypress */
128 #endif /* ROMDEBUG */
130 /**************************************************************************
131 START - Where all the fun begins....
132 **************************************************************************/
141 movw $(cmesg-textstart), %si
147 /* copy to reloc and jump to copy */
150 movw $(reloc>>4), %ax
152 movl $(_C_LABEL(edata)-reloc), %ecx
156 ljmpl $(reloc>>4), $1f-reloc /* Jmp to RELOC:1f */
168 movl $_C_LABEL(edata), %edi
169 movl $_C_LABEL(end), %ecx
176 mov $(rmesg-textstart), %si
180 calll _C_LABEL(real_to_prot)
184 .globl _C_LABEL(exit)
186 call _C_LABEL(prot_to_real)
190 mov $(emesg-textstart), %si
194 /* jump to saved vector */
203 /**************************************************************************
204 GLOBAL DESCRIPTOR TABLE
205 **************************************************************************/
213 .byte 0, 0x00, 0x00, 0
215 #ifdef SUPPORT_LINUX /* additional dummy */
217 .byte 0, 0x00, 0x00, 0
222 flatcodeseg = . - gdt
223 bootcodeseg = . - gdt
225 .byte 0, 0x9f, 0xcf, 0
229 flatdataseg = . - gdt
230 bootdataseg = . - gdt
232 .byte 0, 0x93, 0xcf, 0
234 /* 16 bit real mode */
235 bootrealseg = . - gdt
237 .byte 0, 0x9f, 0x0f, 0
239 /* limits (etc) for data segment in real mode */
240 bootrealdata = . - gdt
242 .byte 0, 0x92, 0x00, 0
251 .word gdtlen-1 /* limit */
256 /**************************************************************************
257 REAL_TO_PROT - Go from REAL mode to Protected Mode
258 **************************************************************************/
265 addr32 /* don't know the syntax for this! */
266 lgdt %cs:gdtarg-reloc
271 mov %eax, %cr0 /* turn on protected mode */
273 /* jump to relocation, flush prefetch queue, and reload %cs */
274 ljmpl $bootcodeseg, $1f
277 /* reload other segment registers */
278 movl $bootdataseg, %eax
282 add $reloc, %esp /* Fix up stack pointer */
283 movl 4(%esp), %eax /* Fix up return Address */
290 /**************************************************************************
291 PROT_TO_REAL - Go from Protected Mode to REAL Mode
292 **************************************************************************/
296 movl 4(%esp), %eax /* Fix up return Address */
299 sub $reloc, %esp /* Adjust stack pointer */
302 * Load the segment registers while still in protected mode.
303 * Otherwise the control bits don't get changed.
304 * The correct values are loaded later.
306 movw $bootrealdata, %ax
311 ljmp $bootrealseg, $1f /* jump to a 16 bit segment */
314 /* clear the PE bit of CR0 */
319 /* make intersegment jmp to flush the processor pipeline
320 * and reload CS register
322 ljmpl $(reloc)>>4, $2f-reloc
324 /* we are in real mode now
325 * set up the real mode segment registers : DS, SS, ES