aboutsummaryrefslogtreecommitdiff
path: root/pc-bios/optionrom/multiboot.S
diff options
context:
space:
mode:
Diffstat (limited to 'pc-bios/optionrom/multiboot.S')
-rw-r--r--pc-bios/optionrom/multiboot.S77
1 files changed, 60 insertions, 17 deletions
diff --git a/pc-bios/optionrom/multiboot.S b/pc-bios/optionrom/multiboot.S
index e6cbefdc92..dafac7392e 100644
--- a/pc-bios/optionrom/multiboot.S
+++ b/pc-bios/optionrom/multiboot.S
@@ -26,6 +26,14 @@
#define MULTIBOOT_MAGIC 0x2badb002
+#define GS_PROT_JUMP 0
+#define GS_GDT_DESC 6
+
+/* Break the translation block flow so -d cpu shows us values */
+#define DEBUG_HERE \
+ jmp 1f; \
+ 1:
+
/* Read a variable from the fw_cfg device.
Clobbers: %edx
Out: %eax */
@@ -44,12 +52,31 @@
bswap %eax
.endm
+/*
+ * Read a blob from the fw_cfg device.
+ * Requires _ADDR, _SIZE and _DATA values for the parameter.
+ *
+ * Clobbers: %eax, %edx, %es, %ecx, %edi
+ */
+#define read_fw_blob(var) \
+ read_fw var ## _ADDR; \
+ mov %eax, %edi; \
+ read_fw var ## _SIZE; \
+ mov %eax, %ecx; \
+ mov $var ## _DATA, %ax; \
+ mov $BIOS_CFG_IOPORT_CFG, %edx; \
+ outw %ax, (%dx); \
+ mov $BIOS_CFG_IOPORT_DATA, %dx; \
+ cld; \
+ DEBUG_HERE \
+ rep insb (%dx), %es:(%edi);
+
.code16
.text
.global _start
_start:
.short 0xaa55
- .byte 1 /* (_end - _start) / 512 */
+ .byte (_end - _start) / 512
push %eax
push %ds
@@ -57,10 +84,6 @@ _start:
xor %ax, %ax
mov %ax, %ds
- /* save old int 19 */
- mov (0x19*4), %eax
- mov %eax, %cs:old_int19
-
/* install our int 19 handler */
movw $int19_handler, (0x19*4)
mov %cs, (0x19*4+2)
@@ -84,15 +107,34 @@ run_multiboot:
mov %cs, %eax
shl $0x4, %eax
- /* fix the gdt descriptor to be PC relative */
- mov (gdt_desc+2), %ebx
- add %eax, %ebx
- mov %ebx, (gdt_desc+2)
+ /* set up a long jump descriptor that is PC relative */
- /* fix the prot mode indirect jump to be PC relative */
+ /* move stack memory to %gs */
+ mov %ss, %ecx
+ shl $0x4, %ecx
+ mov %esp, %ebx
+ add %ebx, %ecx
+ sub $0x20, %ecx
+ sub $0x30, %esp
+ shr $0x4, %ecx
+ mov %cx, %gs
+
+ /* now push the indirect jump decriptor there */
mov (prot_jump), %ebx
add %eax, %ebx
- mov %ebx, (prot_jump)
+ movl %ebx, %gs:GS_PROT_JUMP
+ mov $8, %bx
+ movw %bx, %gs:GS_PROT_JUMP + 4
+
+ /* fix the gdt descriptor to be PC relative */
+ movw (gdt_desc), %bx
+ movw %bx, %gs:GS_GDT_DESC
+ movl (gdt_desc+2), %ebx
+ add %eax, %ebx
+ movl %ebx, %gs:GS_GDT_DESC + 2
+
+ /* Read the bootinfo struct into RAM */
+ read_fw_blob(FW_CFG_INITRD)
/* FS = bootinfo_struct */
read_fw FW_CFG_INITRD_ADDR
@@ -100,7 +142,7 @@ run_multiboot:
mov %ax, %fs
/* ES = mmap_addr */
- read_fw FW_CFG_INITRD_SIZE
+ mov %eax, %fs:0x48
shr $4, %eax
mov %ax, %es
@@ -144,7 +186,7 @@ mmap_done:
real_to_prot:
/* Load the GDT before going into protected mode */
lgdt:
- data32 lgdt %cs:gdt_desc
+ data32 lgdt %gs:GS_GDT_DESC
/* get us to protected mode now */
movl $1, %eax
@@ -152,7 +194,7 @@ lgdt:
/* the LJMP sets CS for us and gets us to 32-bit */
ljmp:
- data32 ljmp *%cs:prot_jump
+ data32 ljmp *%gs:GS_PROT_JUMP
prot_mode:
.code32
@@ -165,8 +207,11 @@ prot_mode:
movl %eax, %fs
movl %eax, %gs
+ /* Read the kernel and modules into RAM */
+ read_fw_blob(FW_CFG_KERNEL)
+
/* Jump off to the kernel */
- read_fw FW_CFG_KERNEL_ADDR
+ read_fw FW_CFG_KERNEL_ENTRY
mov %eax, %ecx
/* EBX contains a pointer to the bootinfo struct */
@@ -180,8 +225,6 @@ ljmp2:
/* Variables */
.align 4, 0
-old_int19: .long 0
-
prot_jump: .long prot_mode
.short 8