I've written some C code that copies the real mode portion of the Linux kernel to 0x90000 and the protected mode portion to 0x100000. This code is running in Protected Mode, the next step from the boot.txt in the x86/i386/ is to be in real mode and jump to the segment of the real mode portion of the Linux Kernel offset offset by 0x20.
After my C code is done coping it will call the LinuxBoot Procedure in the following Code. Please Note that Real Mode code is from the following file.
Code: Select all
.386p
PROT_MODE_CSEG EQU 0x8
PROT_MODE_DSEG EQU 0x10
PSEUDO_RM_CSEG EQU 0x18
PSEUDO_RM_DSEG EQU 0x20
LINUX_SETUP_STACK EQU 0x9000
LINUX_KERNEL_SEGMENT EQU 0x9000
LINUX_KERNEL_ENTRY_POINT EQU 0x9020
.code
_TEXT32 SEGMENT PARA PUBLIC USE32 'CODE16'
ASSUME CS:_TEXT32, DS:NOTHING
org 0x0
;Disable the Interrupts before beginning
cli
; Load the Segment Registers, with Segment Limit
mov eax, PSEUDO_RM_DSEG
mov ss, eax
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
; Load the Interrupt Vector Table
lidt FWORD PTR idt_real
; Clear the PE flag in the CR0 register
mov eax, cr0 ; Get the current CR0
and al, NOT 1 ; Clear the PE bit to enable real mode
mov cr0, eax ; NOW WE'RE IN REALMODE!
; Reload CS
; Try a jmp
;jmp far ptr jumphere
db 0xea
dw 0x20
dw 0x1000
idt_real:
dw 0x3ff ;256 Entries, 4b each =1K
dd 0x0000 ;Real Mode IVT is at 0x0000
_TEXT32 Ends
_TEXT16 SEGMENT PARA PUBLIC USE16 'CODE16'
ASSUME CS:_TEXT16, DS:NOTHING
org 0x20
;Change Bx to linux kernel segment
mov bx, LINUX_KERNEL_SEGMENT
mov ss, bx
mov sp, LINUX_SETUP_STACK
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
;/* jump to start */
;/* ljmp */
; Always jump to LINUX_KERNEL_ENTRY_POINT
db 0xea
dw 0
dw LINUX_KERNEL_ENTRY_POINT
_TEXT16 ends
end
My assembly is the following:
Code: Select all
.586p
PROT_MODE_CSEG EQU 0x8
PROT_MODE_DSEG EQU 0x10
PSEUDO_RM_CSEG EQU 0x18
PSEUDO_RM_DSEG EQU 0x20
LINUX_SETUP_STACK EQU 0x9000
LINUX_KERNEL_SEGMENT EQU 0x9000
LINUX_KERNEL_ENTRY_POINT EQU 0x9020
;Protected Mode Code
_TEXT32 SEGMENT PARA PUBLIC USE32 'CODE32'
ASSUME CS:_TEXT32, DS:NOTHING
PUBLIC LinuxBoot
LinuxBoot PROC
;Copy Real Mode Code to proper location
mov ecx, EndRealCode -StartRealCode
mov esi, StartRealCode
mov edi, 0x10000
cld
rep movsb
;/* just in case, set GDT */
lgdt FWORD PTR gdtdesc ; Load the GDTR
;Jump and hope for the Best
db 0xea
dd 0
dw PSEUDO_RM_CSEG
LinuxBoot ENDP
StartRealCode:
; This contains the Machine Code from linuxboot.asm
EndRealCode:
;/*
; * This is the Global Descriptor Table
; *
; * An entry, a "Segment Descriptor", looks like this:
; *
; * 31 24 19 16 7 0
; * ------------------------------------------------------------
; * | | |B| |A| | | |1|0|E|W|A| |
; * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL| TYPE | BASE 23:16 |
; * | | |D| |L| 19..16| | |1|1|C|R|A| |
; * ------------------------------------------------------------
; * | | |
; * | BASE 15..0 | LIMIT 15..0 |
; * | | |
; * ------------------------------------------------------------
; *
; * Note the ordering of the data items is reversed from the above
; * description.
; */
gdt:
; 0(selector=0x0000): Null descriptor
dw 0x0000
dw 0x0000
db 0x00
db 0x00
db 0x00
db 0x00
; 1(selector=0x0008): Code segment
dw 0xFFFF ; limit: xFFFF
dw 0x0000 ; base : xxxx0000
db 0x00 ; base : xx00xxxx
db 0x9A ; Code e/r, Present, DPL0
db 0xCF ; limit: Fxxxx, Page Gra, 32bit
db 0x00 ; base : 00xxxxxx
; 2(selector=0x0010): Data Segment
dw 0xFFFF ; limit: xffff
dw 0x0000 ; base : xxxx0000
db 0x00 ; base : xx00xxxx
db 0x92 ; Data, Present, DPL0
db 0xCF ; limit: Fxxxx, Page Gra, 32bit
db 0x00 ; base : 00xxxxxx
; 3(selector=0x0018): 16 bit Real Mode Code Segment
dw 0xFFFF ; limit: xffff
dw 0x0000 ; base : xxxx0000
db 0x01 ; base : xx01xxxx
db 0x9E ; Code Conform, Present, DPL0
db 0x00 ;
db 0x00 ; base : 00xxxxxx
; 4(selector=0x0020): 16 bit Real Mode Data Segment
dw 0xFFFF ; limit: xffff
dw 0x0000 ; base : xxxx0000
db 0x01 ; base : xx01xxxx
db 0x92 ; Data, Present, DPL0
db 0x00 ;
db 0x00 ; base : 00xxxxxx
;/* this is the GDT descriptor */
gdtdesc:
dw 0x27 ; size 39 (8 * 5 -1)bytes
dd gdt ; address
_TEXT32 ENDS
END
-Moffatt