You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
298 lines
8.3 KiB
298 lines
8.3 KiB
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 |