6 changed files with 339 additions and 25 deletions
@ -1,15 +1,17 @@
|
||||
#!/usr/bin/bash |
||||
|
||||
if [ "$1" == "build" ] || [ "$1" == "run" ]; then |
||||
nasm -fbin bootloader.nasm -o bootloader.bin |
||||
nasm -fbin kernel.nasm -o kernel.bin |
||||
cat bootloader.bin kernel.bin > SingOS.img |
||||
# if [ "$1" == "build" ] || [ "$1" == "run" ]; then |
||||
# nasm -fbin bootloader.nasm -o bootloader.bin |
||||
# nasm -fbin kernel.nasm -o kernel.bin |
||||
# cat bootloader.bin kernel.bin > SingOS.img |
||||
|
||||
if [ $1 == "run" ]; then |
||||
qemu-system-x86_64 -drive index=0,format=raw,file=SingOS.img |
||||
else |
||||
bash -c "echo;echo;echo 'Press [ENTER] to exit'; read line" |
||||
fi |
||||
fi |
||||
# if [ $1 == "run" ]; then |
||||
# qemu-system-x86_64 -drive index=0,format=raw,file=SingOS.img |
||||
# else |
||||
# bash -c "echo;echo;echo 'Press [ENTER] to exit'; read line" |
||||
# fi |
||||
# fi |
||||
|
||||
echo "Done" |
||||
# echo "Done" |
||||
|
||||
sh build.sh |
@ -0,0 +1,306 @@
|
||||
|
||||
; %define GDT 0xfe00 |
||||
%define GDT_CodeSegIndex 1 |
||||
%define GDT_DataSegIndex 2 |
||||
%define GDT_Selector(DescriptorIndex, TableIndicator, RequestorPrivLevel) ((DescriptorIndex << 3) | ((TableIndicator & 1) << 2) | (RequestorPrivLevel & 0x3)) |
||||
%define GDT_CodeSegmentSelector GDT_Selector(GDT_CodeSegIndex, 0, 0) |
||||
%define GDT_DataSegmentSelector GDT_Selector(GDT_DataSegIndex, 0, 0) |
||||
|
||||
%define VIDEO 0xB8000 |
||||
|
||||
; GDT Stuff |
||||
%define Data 0000b |
||||
%define DataMutable 0010b |
||||
%define DataShrink 0100b |
||||
%define DataShrinkMutable 0110b |
||||
%define Code 1000b |
||||
%define CodeRead 1010b |
||||
%define CodeOwnRing 1100b |
||||
%define CodeOwnRingRead 1110b |
||||
|
||||
%macro GDT_NULL_ENTRY 1 ; address |
||||
%assign address %1 |
||||
lea di, [address] |
||||
xor ax, ax |
||||
mov cx, 4 |
||||
rep stosw |
||||
%endmacro |
||||
|
||||
%macro GDT_ENTRY 6 ; address base limit type privilege bits32 |
||||
%assign address %1 |
||||
|
||||
%assign base %2 |
||||
%assign limit %3 |
||||
|
||||
%assign type (%4 & 0xf) |
||||
%assign reserved (1<<4) |
||||
%assign privilege ((%5 & 0x3) << 5) |
||||
%assign present (1<<7) |
||||
%assign access (present | privilege | reserved | type) |
||||
|
||||
%assign bits32 ((%6 & 1) << 2) |
||||
%assign granularity (1<<3) |
||||
%assign flags (granularity | bits32) |
||||
|
||||
%assign limit_0_15 (limit & 0xffff) |
||||
%assign limit_16_19 ((limit >> 16) & 0xf) |
||||
%assign base_0_15 (base & 0xffff) |
||||
%assign base_16_23 ((base >> 16) & 0xff) |
||||
%assign base_24_31 ((base >> 24) & 0xff) |
||||
|
||||
mov WORD [es:(address + 0)], limit_0_15 |
||||
mov WORD [es:(address + 2)], base_0_15 |
||||
mov WORD [es:(address + 4)], base_16_23 | (access << 8) |
||||
mov WORD [es:(address + 6)], limit_16_19 | (flags << 4) | (base_24_31 << 8) |
||||
%endmacro |
||||
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
Enable_A20: |
||||
; Enables A20 gate using:the BIOS, keyboard controller, or Fast A20 |
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
pushad ;Preserve registers |
||||
pushfd ;Preserve EFLAGS because we might disable interrupts |
||||
mov ax,0x2402 ;INT 15h AX=2402h: Query A20 status |
||||
int 0x15 ;Check to see if A20 gate is enabled |
||||
jc A20_No_BIOS ;Error? Don't use BIOS to enable gate |
||||
test al,1 ;Test Bit 0 of AL |
||||
je A20_Enabled ;A20 gate already enabled |
||||
mov ax,0x2401 ;INT 15h AX=2401h: Enable A20 gate |
||||
int 0x15 ;Use BIOS to enable A20 gate |
||||
jc A20_No_BIOS ;Error? Don't use BIOS to enable gate |
||||
or ah,ah ;Test AH |
||||
jnz A20_No_BIOS ;Non-zero? A20 gate may not be enabled |
||||
A20_Enabled: |
||||
popfd ;Restore EFLAGS |
||||
popad ;Restore registers |
||||
ret ;Return |
||||
A20_No_BIOS: |
||||
mov ax,0x2403 ;INT 15h AX=2403h: Query A20 support |
||||
int 0x15 ;Call BIOS to find out how the A20 gate can be enabled |
||||
jc A20_KBD ;Error? Assume that keyboard controller is the only option |
||||
test bx,1 ;Bit 0:Keyboard controller supported |
||||
je A20_KBD ;BIOS indicates that keyboard controller is supported |
||||
test bx,2 ;Bit 1:Fast A20 supported |
||||
je FAST_A20 ;BIOS indicated that Fast A20 is supported |
||||
call Check_A20 ;Test A20 gate manually |
||||
jc A20_Enabled ;A20 gate already enabled |
||||
A20_Fail: |
||||
call A20_OUT_Wait ;"Unable to enable A20 gate!" |
||||
cli ;Disable interrupts |
||||
hlt ;Halt machine |
||||
FAST_A20: |
||||
in al,0x92 ;Read System Control Port A |
||||
test al,2 ;Test Fast A20 bit |
||||
jnz A20_Fail ;Bit already set, failed to enable A20 gate |
||||
or al,2 ;Set Bit 1:Enable Fast A20 |
||||
and al,0xFE ;Always clear Bit 0 so that machine does not reboot |
||||
out 0x92,al ;Write to port 92h |
||||
call Check_A20 ;Check A20 gate |
||||
jc A20_Enabled ;Success? |
||||
cli ;No? something must have gone wrong |
||||
hlt ;Clear interrupts and halt machine |
||||
A20_KBD: |
||||
cli ;Disable interrupts |
||||
mov cx,50 ;Number of attempts to enable gate |
||||
Use_KBD: |
||||
call A20_OUT_Wait ;Wait for keyboard |
||||
mov al,0xAD ;Disable Keyboard |
||||
out 0x64,al ;Wait for Keyboard |
||||
mov al,0xD0 ;Read Controller Output Port |
||||
out 0x64,al |
||||
call A20_IN_Wait ;Wait for Keyboard |
||||
in al,0x60 ;Read Data Port |
||||
push ax ;Save |
||||
call A20_OUT_Wait ;Wait for Keyboard |
||||
mov al,0xD1 ;Write Controller Output Port |
||||
out 0x64,al |
||||
call A20_OUT_Wait ;Wait for Keyboard |
||||
pop ax ;Get port data back |
||||
or al,10b ;Bit 1: Enable A20 gate |
||||
out 0x60,al ;Write to data port |
||||
call A20_OUT_Wait ;Wait for Keyboard |
||||
mov al,0xAE ;Enable Keyboard |
||||
out 0x64,al |
||||
call A20_OUT_Wait ;Wait for Keyboard |
||||
call Check_A20 ;Verify that gate is enabled |
||||
jc A20_Enabled ;Yes? Return |
||||
loop Use_KBD ;No? Keep trying |
||||
jmp A20_Fail ;Could not enable gate after 50 tries |
||||
A20_OUT_Wait: |
||||
in al,0x64 ;Read status register |
||||
test al,10b ;Is port ready? |
||||
jnz A20_OUT_Wait ;Nope, wait |
||||
ret ;Yep, continue |
||||
A20_IN_Wait: |
||||
in al,0x64 ;Read status register |
||||
test al,1b ;Is port ready? |
||||
jz A20_IN_Wait ;Nope, wait |
||||
ret ;Yep, continue |
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
Check_A20: |
||||
; Test if A20 gate is enabled by comaparing the value in FFFF:7E0E |
||||
; with the VBR boot signature at 0000:7DFE |
||||
; Out: Carry flag set if A20 gate is enabled |
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
|
||||
pushad ;Preserve registers |
||||
push es |
||||
mov ax, 0xFFFF |
||||
mov es, ax ;Extra segment:FFFF |
||||
cmp WORD [es:0x7DFE + 16], 0xAAFF ;See if boot signature is wrapped at FFFF:7E0E (Meaning FFFF:7E0E = 0:7DFE) |
||||
stc ; Assume we didn't wrap, yes A20 |
||||
jne .End |
||||
clc ; We did wrap, no A20 |
||||
.End: |
||||
pop es |
||||
popad |
||||
ret |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
Go32Bit: |
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
call Enable_A20 |
||||
|
||||
; Set screen mode |
||||
mov ax, 0x0003 ; AH=0 (Change video mode), AL=13h (Mode) = 320x200 - 256 colors |
||||
mov bx, 0x0000 |
||||
int 0x10 ; Video BIOS interrupt |
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
; Global Descriptor Table ; |
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
mov ax, 0x1000 |
||||
mov es, ax |
||||
mov cx, 1024 |
||||
lea si, [GO32_COPY_BEGIN] |
||||
xor di, di |
||||
rep movsb |
||||
|
||||
%assign GDT_SIZE 0 |
||||
|
||||
GDT_NULL_ENTRY 0 |
||||
%assign GDT_SIZE (GDT_SIZE+8) |
||||
|
||||
GDT_ENTRY (GDT_CodeSegIndex*8), 0x00000000, 0xffffffff, CodeRead, 0, 1 |
||||
%assign GDT_SIZE (GDT_SIZE+8) |
||||
|
||||
GDT_ENTRY (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 0x1000*16 + 512 ; Absolute address |
||||
dw GDT_CodeSegmentSelector ; Descriptor Selector |
||||
|
||||
GDT_Record: |
||||
dw GDT_SIZE - 1 ; Size of GDT in bytes minus 1 |
||||
dd 0x1000*16 ; Linear address of GDT |
||||
|
||||
|
||||
|
||||
align 512 |
||||
GO32_COPY_BEGIN: |
||||
segment Go32Bit vstart=(0x1000*16) |
||||
BITS 32 |
||||
GDT: |
||||
.null_selector: dq 0 |
||||
.code_selector: dq 0 |
||||
.data_selector: dq 0 |
||||
align 512 |
||||
ProtectedModeBaby: |
||||
|
||||
; 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: |
||||
cli |
||||
hlt |
||||
jmp HALT |
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;; |
||||
;; Strings |
||||
;;;;;;;;;;;;;;;;;;;;;;;; |
||||
ProtectedWelcomeStr: db " Placeholder for SingOS - 32 bit edition! ", 0 |
||||
align 512 |
Loading…
Reference in new issue