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

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