loaderMain:
;; This is the main OS loader driver code. It calls a number
;; of other routines for the puposes of detecting hardware,
;; loading the kernel, etc. After everything else is done, it
;; switches the processor to protected mode and starts the kernel.
cli
;; Make sure all of the data segment registers point to the same
;; segment as the code segment
mov EAX, (LDRCODESEGMENTLOCATION / 16)
mov DS, EAX
mov ES, EAX
mov FS, EAX
mov GS, EAX
;; Now ensure the stack segment and stack pointer are set to
;; something more appropriate for the loader
mov EAX, (LDRSTCKSEGMENTLOCATION / 16)
mov SS, EAX
mov SP, LDRSTCKBASE
sti
;; The boot sector code should have put the boot drive number in DL
xor DH, DH
mov word [DRIVENUMBER], DX
;; If we are not booting from a floppy, then the boot sector code
;; should have put a pointer to the MBR record for this partition
;; in SI. Copy the partition entry.
cmp word [DRIVENUMBER], 80h
jb .notHDD
push DS
push 0
pop DS
mov CX, 16
mov DI, PARTENTRY
rep movsb
pop DS
.notHDD:
;; Set the text display to a good mode, clearing the screen
push word 0
call loaderSetTextDisplay
;; Initialize SP...
add SP, 2
;; Print Vanesika initialization messages
mov SI, LOADMSG1
mov DL, FOREGROUNDCOLOR
call loaderPrint
call loaderPrintNewline
mov SI, LOADMSG2
call loaderPrint
call loaderPrintNewline
call loaderPrintNewline
;; Gather information about the boot device
call bootDevice
;; Get FAT filesystem info from the boot sector
call fatInfo
;; Calculate values that will help us deal with the filesystem
;; volume correctly
call loaderCalcVolInfo
;; Before we print any other info, determine whether the user wants
;; to see any hardware info messages. If the BOOTINFO file exists,
;; then we print the messages
push word BOOTINFO
call loaderFindFile
add SP, 2 ;; SP+=2
mov word [PRINTINFO], AX
;; Print out the boot device information
cmp word [PRINTINFO], 1
jne .noPrint1
call printBootDevice
.noPrint1:
;; Call the routine to do the hardware detection
call loaderDetectHardware
;; Do a fatal error check before loading
call fatalErrorCheck
call loaderPrintNewline
mov SI, LOADING
mov DL, FOREGROUNDCOLOR
call loaderPrint
call loaderPrintNewline
;; Load the kernel ---------------------------------------------------------------------------
call loaderLoadKernel ;; make it rezident
;; -------------------------------------------------------------------------------------------
;; Make sure the kernel load was successful
cmp AX, 0
jge .okLoad
add byte [FATALERROR], 1
.okLoad:
;; Enable the A20 address line so that we will have access to the
;; entire extended memory space.
call loaderEnableA20
;; Check for fatal errors before attempting to start the kernel
call fatalErrorCheck
;; Check if we find a graphic mode
cmp word [KERNELGMODE], 0
je .noGraphics
;; Get the graphics mode for the kernel and switch to it
push word [KERNELGMODE]
call loaderSetGraphicDisplay
add SP, 2
.noGraphics:
;; Disable the cursor
mov CX, 2000h
mov AH, 01h
int 10h
;; Disable interrupts. The kernel's initial state will be with
;; interrupts disabled. It will have to do the appropriate setup
;; before re-enabling them.
cli
;; Set up a temporary GDT (Global Descriptor Table) for the protected
;; mode switch. The kernel will replace it later with a permanent
;; version. We will discuss about GTD later.
lgdt [GDTSTART]
;; Here's the big moment. Switch permanently to protected mode.
mov EAX, CR0
or AL, 01h
mov CR0, EAX
BITS 32
;; Set EIP to protected mode values by spoofing a far jump
db 0EAh
dw .returnLabel, LDRCODESELECTOR
.returnLabel:
;; Now enable very basic paging
call pagingSetup
;; Make the data and stack segment registers contain correct
;; values for the kernel in protected mode
;; First the data registers (all point to the whole memory as data)
mov EAX, PRIV_DATASELECTOR
mov DS, EAX
mov ES, EAX
mov FS, EAX
mov GS, EAX
;; Now the stack registers
mov EAX, PRIV_STCKSELECTOR
mov SS, EAX
mov EAX, KERNELVIRTUALADDRESS
add EAX, dword [LDRCODESEGMENTLOCATION + KERNELSIZE]
add EAX, (KERNELSTACKSIZE - 4)
mov ESP, EAX
;; Pass the kernel arguments.
;; First check the hardware structure
push dword (LDRCODESEGMENTLOCATION + HARDWAREINFO)
;; Next the amount of used kernel memory. We need to add the
;; size of the stack we allocated to the kernel image size
mov EAX, dword [LDRCODESEGMENTLOCATION + KERNELSIZE]
add EAX, KERNELSTACKSIZE
push EAX
;; Waste some space on the stack that would normally be used to
;; store the return address in a call. This will ensure that the
;; kernel's arguments are located where gcc thinks they should be
;; for a "normal" function call. We will use a NULL return address
push dword 0
;; Start the kernel.
jmp PRIV_CODESELECTOR:KERNELVIRTUALADDRESS
BITS 16
No comments:
Post a Comment