BITS 16
|
|
%include "bootloader_macros.inc"
|
|
%define STAGE1_BASE 0x7c00
|
|
%define STAGE2_BASE (STAGE1_BASE + 0x200)
|
|
%define PROTECED_MODE_BASE (STAGE2_BASE + 0x200)
|
|
%define GDT 0x0800
|
|
%define GDT_CodeSegIndex 1
|
|
%define GDT_DataSegIndex 2
|
|
%define GDT_CodeSegmentSelector GDT_Selector(GDT_CodeSegIndex, 0, 0)
|
|
%define GDT_DataSegmentSelector GDT_Selector(GDT_DataSegIndex, 0, 0)
|
|
%if 1; TEXT MODE
|
|
%define VIDEO 0xB8000
|
|
%else
|
|
%define VIDEO 0xA0000
|
|
%endif
|
|
|
|
%define STACK_POINTER_MAX STAGE1_BASE-2 ; Stack grows downwards from right under stage_1
|
|
|
|
; /$$$$$$ /$$ /$$
|
|
; /$$__ $$ | $$ /$$$$
|
|
; | $$ \__//$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |_ $$
|
|
; | $$$$$$|_ $$_/ |____ $$ /$$__ $$ /$$__ $$ | $$
|
|
; \____ $$ | $$ /$$$$$$$| $$ \ $$| $$$$$$$$ | $$
|
|
; /$$ \ $$ | $$ /$$ /$$__ $$| $$ | $$| $$_____/ | $$
|
|
; | $$$$$$/ | $$$$/| $$$$$$$| $$$$$$$| $$$$$$$ /$$$$$$
|
|
; \______/ \___/ \_______/ \____ $$ \_______//$$$$$$|______/
|
|
; /$$ \ $$ |______/
|
|
; | $$$$$$/
|
|
; \______/
|
|
segment Stage1 vstart=STAGE1_BASE
|
|
Stage1:
|
|
jmp short SkipWeirdBIOSShite
|
|
nop ; Used later as a FLAG byte for extended INT 13 Disk Func.'s (See instruction at: 7CADh).
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Disk description table, to make it a valid floppy
|
|
; Note: some of these values are hard-coded in the source!
|
|
; Values are those used by IBM for 1.44 MB, 3.5" diskette
|
|
; NOTE(jakob): From MikeOS
|
|
; Why do we need this... damn BIOS
|
|
|
|
; OEMLabel db "SingOs " ; Disk label
|
|
%if 1
|
|
times 40-($-$$) db 0
|
|
%else
|
|
BytesPerSector dw 512 ; Bytes per sector
|
|
SectorsPerCluster db 1 ; Sectors per cluster
|
|
ReservedForBoot dw 1 ; Reserved sectors for boot record
|
|
NumberOfFats db 2 ; Number of copies of the FAT
|
|
RootDirEntries dw 224 ; Number of entries in root dir
|
|
; (224 * 32 = 7168 = 14 sectors to read)
|
|
LogicalSectors dw 2880 ; Number of logical sectors
|
|
MediumByte db 0xF0 ; Medium descriptor byte
|
|
SectorsPerFat dw 9 ; Sectors per FAT
|
|
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
|
|
Sides dw 2 ; Number of sides/heads
|
|
HiddenSectors dd 0 ; Number of hidden sectors
|
|
LargeSectors dd 0 ; Number of LBA sectors
|
|
DriveNo dw 0 ; Drive No: 0
|
|
Signature db 0 ; Drive signature: 41 for floppy
|
|
VolumeID dd 0x00000000 ; Volume ID: any number
|
|
VolumeLabel db "SingOs "; Volume Label: any 11 chars
|
|
FileSystem db "VSFS " ; File system type: don't change!
|
|
%endif
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
SkipWeirdBIOSShite:
|
|
cli ; Disable interrupts
|
|
|
|
; Setup segments
|
|
jmp 0x0000:CanonicalBootloaderStart ; CS:IP = 0x0000:7Cxx where xx is
|
|
; the size of the BPB + instructions
|
|
; before CanonicalBootloaderStart
|
|
CanonicalBootloaderStart:
|
|
xor ax, ax
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov fs, ax
|
|
mov ss, ax
|
|
; Setup stack
|
|
mov sp, STACK_POINTER_MAX
|
|
sti ; Enable interrupts
|
|
cld
|
|
|
|
mov [BootDriveNumber], dl ; Save boot device number
|
|
|
|
mov eax, 0 ; Needed for some older BIOSes
|
|
|
|
mov si, FirstStageString
|
|
call PrintString
|
|
|
|
mov cx, 5 ; Try five times
|
|
|
|
.TryReadLoop:
|
|
xor ax, ax ; Reset disk controller
|
|
mov es, ax ; Just to be damn sure! (Still canonical 0 segment)
|
|
movzx dx, byte [BootDriveNumber];
|
|
int 0x13
|
|
|
|
mov ax, 0x0202 ; Read one sector
|
|
mov cx, 0x0002 ; Cylinder 0, sector 2
|
|
movzx dx, byte [BootDriveNumber] ; Head zero, drive number
|
|
mov bx, STAGE2_BASE ; Where we put the second stage
|
|
int 0x13
|
|
|
|
jnc .BreakTryReadLoop
|
|
loop .TryReadLoop
|
|
jmp DiskReadError
|
|
.BreakTryReadLoop:
|
|
|
|
jmp STAGE2_BASE
|
|
|
|
DiskReadError:
|
|
mov si, DiskReadErrorStr
|
|
call PrintString
|
|
xor ax, ax
|
|
int 16h ; Wait for keystroke
|
|
xor ax, ax
|
|
int 19h ; Reboot the system
|
|
jmp DiskReadError
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
%include "bootloader_bios_functions.inc"
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
FirstStageString: db "Loading stage 2...", 13, 10, 0
|
|
DiskReadErrorStr: db "Disk read error. Press any key to reboot.", 0
|
|
BootDriveNumber db 0
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
times 512-($-$$)-2 db 0 ; Zero pad to boot signature
|
|
db 0x55, 0xAA ; Boot signature
|
|
|
|
; /$$$$$$ /$$ /$$$$$$
|
|
; /$$__ $$ | $$ /$$__ $$
|
|
; | $$ \__//$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ |__/ \ $$
|
|
; | $$$$$$|_ $$_/ |____ $$ /$$__ $$ /$$__ $$ /$$$$$$/
|
|
; \____ $$ | $$ /$$$$$$$| $$ \ $$| $$$$$$$$ /$$____/
|
|
; /$$ \ $$ | $$ /$$ /$$__ $$| $$ | $$| $$_____/ | $$
|
|
; | $$$$$$/ | $$$$/| $$$$$$$| $$$$$$$| $$$$$$$ | $$$$$$$$
|
|
; \______/ \___/ \_______/ \____ $$ \_______//$$$$$$|________/
|
|
; /$$ \ $$ |______/
|
|
; | $$$$$$/
|
|
; \______/
|
|
|
|
; org STAGE2_BASE
|
|
segment Stage2 vstart=STAGE2_BASE
|
|
Stage2:
|
|
call PrintRealAddress
|
|
CRLF
|
|
|
|
mov si, SecondStageString
|
|
call PrintString
|
|
|
|
mov si, EnablingA20Str
|
|
call PrintString
|
|
|
|
call Enable_A20
|
|
mov al, '0' >> 1
|
|
call Check_A20
|
|
rcl al, 1
|
|
mov byte [A20Status.Bit], al
|
|
|
|
mov si, A20Status
|
|
call PrintString
|
|
|
|
mov ax, 0x0003 ; AH=0 (Change video mode), AL=13h (Mode) = 320x200 - 256 colors
|
|
mov bx, 0x0000
|
|
int 0x10 ; Video BIOS interrupt
|
|
|
|
%if 0 ; VESA test (Totally wrong!!!! read up!)
|
|
; mov ax, 0x4f02 ; VESA mode
|
|
; mov bx, 0x0301 ; 132 cols by 60 rows
|
|
; int 0x10 ; Video BIOS interrupt
|
|
%endif
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Global Descriptor Table ;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
%assign GDT_SIZE 0
|
|
|
|
GDT_NULL_ENTRY GDT
|
|
%assign GDT_SIZE (GDT_SIZE+8)
|
|
|
|
GDT_ENTRY (GDT + (GDT_CodeSegIndex*8)), 0x00000000, 0xffffffff, CodeRead, 0, 1
|
|
%assign GDT_SIZE (GDT_SIZE+8)
|
|
|
|
GDT_ENTRY (GDT + (GDT_DataSegIndex*8)), 0x00000000, 0xffffffff, DataMutable, 0, 1
|
|
%assign GDT_SIZE (GDT_SIZE+8)
|
|
|
|
cli
|
|
lgdt [GDT_Record]
|
|
|
|
mov eax, cr0
|
|
or al, 1 ; set PE (Protection Enable) bit in CR0 (Control Register 0)
|
|
mov cr0, eax
|
|
|
|
jmp ClearPrefetchQueue
|
|
nop
|
|
nop
|
|
ClearPrefetchQueue:
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Manually assembled long jump
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
db 0x66 ; 32bit override
|
|
db 0xea ; Long jump
|
|
dd PROTECED_MODE_BASE ; Absolute address
|
|
dw GDT_CodeSegmentSelector ; Descriptor Selector
|
|
|
|
; jmp GDT_CodeSegmentSelector:ProtectedModeBaby ; 8: is for the first descriptor in the GDT that is not the null-descriptor
|
|
HALT
|
|
|
|
GDT_Record:
|
|
dw GDT_SIZE - 1 ; Size of GDT in bytes minus 1
|
|
dd GDT ; Linear address of GDT
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
%include "bootloader_A20.nasm"
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
SecondStageString: db "This is the second stage!", 13, 10, 0
|
|
EnablingA20Str: db "Enabling A20...", 13, 10, 0
|
|
A20Status: db "A20_Enabled="
|
|
.Bit: db '0', 13, 10, 0
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
times 512-($-$$) db 0
|
|
|
|
BITS 32
|
|
segment ProtectedModeBaby vstart=PROTECED_MODE_BASE
|
|
ProtectedModeBaby:
|
|
; Code segment updated by the long jump here
|
|
|
|
; Update Other Segments
|
|
mov ax, GDT_DataSegmentSelector
|
|
mov ds, ax
|
|
mov ss, ax
|
|
mov es, ax
|
|
mov fs, ax
|
|
mov gs, ax
|
|
|
|
; Setup stack
|
|
mov esp, 0xffffffff
|
|
|
|
mov ecx, 0
|
|
mov edx, 0
|
|
lea edi, [VIDEO]
|
|
mov ax, 0x4000
|
|
LoopRows:
|
|
LoopCols:
|
|
mov bl, cl
|
|
xor bl, dl
|
|
shl bl, 4
|
|
mov ah, bl
|
|
ror bl, 1
|
|
xor ah, bl
|
|
and ah, 0x70
|
|
mov al, dl
|
|
add al, cl
|
|
and al, 4
|
|
ror al, 1
|
|
or ah, al
|
|
mov al, 0
|
|
mov WORD [edi], ax
|
|
inc edi
|
|
inc edi
|
|
inc ecx
|
|
cmp ecx, 80
|
|
je BreakLoopCols
|
|
jmp LoopCols
|
|
BreakLoopCols:
|
|
mov ecx, 0
|
|
inc edx
|
|
cmp edx, 25
|
|
je BreakLoopRows
|
|
jmp LoopRows
|
|
BreakLoopRows:
|
|
|
|
WriteProtectedModeString:
|
|
cld
|
|
lea esi, [ProtectedWelcomeStr]
|
|
lea edi, [VIDEO+(80*2)*12+19*2]
|
|
.print_loop:
|
|
mov al, BYTE [esi]
|
|
test al, al
|
|
jz .break_print_loop
|
|
mov BYTE [edi], al
|
|
mov BYTE [edi+1], 0x0f
|
|
inc esi
|
|
inc edi
|
|
inc edi
|
|
jmp .print_loop
|
|
.break_print_loop:
|
|
|
|
HALT
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Strings
|
|
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
ProtectedWelcomeStr: db " Placeholder for SingOS - 32 bit edition! ", 0
|