//
// This file may be distributed under the terms of the GNU GPLv3 license.
-#include "config.h"
-
-#define PROTECTED_MODE_CS (2 << 3) // 0x10
-#define PROTECTED_MODE_DS (3 << 3) // 0x18
-#define REAL_MODE_CS (4 << 3) // 0x20
-#define REAL_MODE_DS (5 << 3) // 0x28
+#include "config.h" // CONFIG_*
+#include "ioport.h" // PORT_A20
+#include "bregs.h" // CR0_*
+#include "../out/asm-offsets.h" // BREGS_*
/****************************************************************
ORG 0xe05b
post16:
+ // enable cache
+ movl %cr0, %eax
+ andl $~(CR0_CD|CR0_NW), %eax
+ movl %eax, %cr0
+
// init the stack pointer
RESET_STACK
cli
// enable a20
- inb $0x92, %al
- orb $0x02, %al
- outb %al, $0x92
+ inb $PORT_A20, %al
+ orb $A20_ENABLE_BIT, %al
+ outb %al, $PORT_A20
// Set segment descriptors
lidt %cs:pmode_IDT_info
lgdt %cs:rombios32_gdt_48
- // set PE bit in CR0
- movl %cr0, %eax
- orb $0x01, %al
- movl %eax, %cr0
+ // Enable protected mode
+ movl %cr0, %eax
+ orl $CR0_PE, %eax
+ movl %eax, %cr0
// start protected mode code
- ljmpl $PROTECTED_MODE_CS, $(BUILD_BIOS_ADDR + 1f)
+ ljmpl $SEG32_MODE32_CS, $(BUILD_BIOS_ADDR + 1f)
.code32
1:
// init data segments
- movl $PROTECTED_MODE_DS, %eax
+ movl $SEG32_MODE32_DS, %eax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
__call16_from32:
pushl %eax
- // Jump to 16bit mode
- ljmpw $REAL_MODE_CS, $1f
-
- .code16gcc
-1:
// restore data segment limits to 0xffff
- movw $REAL_MODE_DS, %ax
+ movw $SEG32_MODE16_DS, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
- // reset PE bit in CR0
+ // disable a20
+ inb $PORT_A20, %al
+ andb $~A20_ENABLE_BIT, %al
+ outb %al, $PORT_A20
+
+ // Jump to 16bit mode
+ ljmpw $SEG32_MODE16_CS, $1f
+
+ .code16gcc
+1:
+ // Disable protected mode
movl %cr0, %eax
- andb $0xfe, %al
+ andl $~CR0_PE, %eax
movl %eax, %cr0
// far jump to flush CPU queue after transition to real mode
// Setup for iretw call
pushw $SEG_BIOS
pushw $1f // return point
- pushw 0x20(%eax) // flags
- pushl 0x1c(%eax) // CS:IP
+ pushw BREGS_flags(%eax) // flags
+ pushl BREGS_ip(%eax) // CS:IP
// Load calling registers.
- movl 0x04(%eax), %edi
- movl 0x08(%eax), %esi
- movl 0x0c(%eax), %ebx
- movl 0x10(%eax), %edx
- movl 0x14(%eax), %ecx
- movw 0x02(%eax), %es // XXX - should load %ds too
- movl 0x18(%eax), %eax
+ movl BREGS_edi(%eax), %edi
+ movl BREGS_esi(%eax), %esi
+ movl BREGS_ebx(%eax), %ebx
+ movl BREGS_edx(%eax), %edx
+ movl BREGS_ecx(%eax), %ecx
+ movw BREGS_es(%eax), %es
+ movw BREGS_ds(%eax), %ds
+ movl %ss:BREGS_eax(%eax), %eax
// Invoke call
iretw // XXX - just do a lcalll
pushfw
pushl %eax
movl 0x06(%esp), %eax
- movl %ecx, %ss:0x14(%eax) // Save %ecx
+ movl %ecx, %ss:BREGS_ecx(%eax)
+ movw %ds, %ss:BREGS_ds(%eax)
movw %ss, %cx
- movw %cx, %ds // Restore %ds == %ss
+ movw %cx, %ds // Restore %ds == %ss
popl %ecx
- movl %ecx, 0x18(%eax) // Save %eax
+ movl %ecx, BREGS_eax(%eax)
popw %cx
- movw %cx, 0x20(%eax) // Save flags
+ movw %cx, BREGS_flags(%eax)
// Store remaining registers
- movw %es, 0x02(%eax)
- movl %edi, 0x04(%eax)
- movl %esi, 0x08(%eax)
- movl %ebx, 0x0c(%eax)
- movl %edx, 0x10(%eax)
+ movw %es, BREGS_es(%eax)
+ movl %edi, BREGS_edi(%eax)
+ movl %esi, BREGS_esi(%eax)
+ movl %ebx, BREGS_ebx(%eax)
+ movl %edx, BREGS_edx(%eax)
// Remove %eax
popl %eax
lidtl (BUILD_BIOS_ADDR + pmode_IDT_info)
lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48)
movl $BUILD_STACK_ADDR, %esp
- ljmpl $PROTECTED_MODE_CS, $_code32__start
+ ljmpl $SEG32_MODE32_CS, $_code32__start
.code16gcc
+// Shutdown a CPU. We want this in the 0xf000 section to ensure that
+// the code wont be overwritten with something else. (Should
+// something spurious wake up the CPU, we want to be sure that the hlt
+// insn will still be present and will shutdown the CPU.)
+ .global permanent_halt
+permanent_halt:
+ cli
+1: hlt
+ jmp 1b
+
/****************************************************************
* GDT and IDT tables
rombios32_gdt:
.word 0, 0, 0, 0
.word 0, 0, 0, 0
- // 32 bit flat code segment (PROTECTED_MODE_CS)
+ // 32 bit flat code segment (SEG32_MODE32_CS)
.word 0xffff, 0, 0x9b00, 0x00cf
- // 32 bit flat data segment (PROTECTED_MODE_DS)
+ // 32 bit flat data segment (SEG32_MODE32_DS)
.word 0xffff, 0, 0x9300, 0x00cf
- // 16 bit code segment base=0xf0000 limit=0xffff (REAL_MODE_CS)
+ // 16 bit code segment base=0xf0000 limit=0xffff (SEG32_MODE16_CS)
.word 0xffff, 0, 0x9b0f, 0x0000
- // 16 bit data segment base=0x0 limit=0xffff (REAL_MODE_DS)
+ // 16 bit data segment base=0x0 limit=0xffff (SEG32_MODE16_DS)
.word 0xffff, 0, 0x9300, 0x0000
// We need a copy of this string in the 0xf000 segment, but we are not