diff --git a/src/boot/loader16.inc b/src/boot/loader16.inc new file mode 100644 index 0000000..56d9840 --- /dev/null +++ b/src/boot/loader16.inc @@ -0,0 +1,88 @@ +;=----------------------------------------------------------------------------=; +; GNU GPL OS/K ; +; ; +; Authors: spectral` ; +; NeoX ; +; ; +; Desc: Kernel (second stage) Loader for OS/K INCLUDED FUNCTIONS ; +; (x86_64 architecture only) ; +;=----------------------------------------------------------------------------=; +[BITS 16] + +disable_cursor: + pushf + push eax + push edx + mov dx, 0x3D4 + mov al, 0xA ; low cursor shape register + out dx, al + inc dx + mov al, 0x20 ; bits 6-7 unused, bit 5 disables the cursor, bits 0-4 control the cursor shape + out dx, al + pop edx + pop eax + popf + ret + +get_dimensions: + push eax + push ebx + mov ah, 0x0F + int 0x10 + mov [VGA_HEIGHT], ah + mov [VIDEO_MODE], al + pop ebx + pop eax + ret + +Is64bits: +;-----------------------------------------------------------------------; +; Checks if the CPU is compatible with 64-bits operating systems ; +; If the 21th bit of the eax register is set, then CPUID is supported ; +; We then test CPUID's result to see if long mode is supported ; +;-----------------------------------------------------------------------; + pushfd ; recovering the flags in eax + pop eax + mov ecx, eax + xor eax, 0x200000 + push eax + popfd + pushfd + pop eax + xor eax, ecx + shr eax, 21 + and eax, 1 ; magical spell of murta + push ecx + popfd + test eax, eax + jz .NonCompat ; if (CPUID non supporté) goto NonCompat + mov eax, 0x80000000 + cpuid + cmp eax, 0x80000001 + jb .NonCompat ; if (eax <= 0x80000001) goto NonCompat + mov eax, 0x80000001 + cpuid + test edx, 1 << 29 + jz .NonCompat ; if (edx != 1 << 29) goto NonCompat + ret ; back to mbr.s +.NonCompat: + stc + ret + +PrintB: +;---------------------------------------------------; +; Print out a simple string. ; +; ; +; Expects: DS:SI = String to print ; +; ; +; Returns: None ; +; ; +;---------------------------------------------------; + lodsb ; Load byte from ds:si to al + or al, al ; If al is empty stop looping + jz .done ; Done looping and return + mov ah, 0x0e ; Teletype output + int 0x10 ; Video interupt + jmp PrintB ; Loop untill string is null + .done: + ret diff --git a/src/boot/loader64.inc b/src/boot/loader64.inc new file mode 100644 index 0000000..2e29af6 --- /dev/null +++ b/src/boot/loader64.inc @@ -0,0 +1,74 @@ +;=----------------------------------------------------------------------------=; +; GNU GPL OS/K ; +; ; +; Authors: spectral` ; +; NeoX ; +; ; +; Desc: Kernel (second stage) Loader for OS/K INCLUDED FUNCTIONS ; +; (x86_64 architecture only) ; +;=----------------------------------------------------------------------------=; +[BITS 64] + +clear: +;-----------------------------------------------------------------------; +; x64/LM Clear Text Screen Function ; +;-----------------------------------------------------------------------; + mov qword [NextTRAM], TRAM + mov edi, TRAM + push rsi + push rdi + push rcx + mov ah, 0 + mov al, 0 + mov rcx, 0x4000 ; traditionnal value + rep stosw ; fill screen with al while cx > 0 + pop rcx + pop rsi + pop rdi + ret + +write: +;-----------------------------------------------------------------------; +; x64/LM Text Printing Functions ; +; bl : color code ; +; esi : string address ; +;-----------------------------------------------------------------------; + mov edi, [NextTRAM] ;TRAM ADDRESS + push rsi + push rdi +.pLoop: + lodsb + cmp al, 0 ; while @al, i.e. while we're not hitting '\0' + je .pEnd + cmp al, 0x0A ; LF + je .lf + cmp al, 0x0D ; CR + je .cr + stosb ; text subpixel + mov al, bl + stosb ; color subpixel + add qword [NextTRAM], 0x2 ; Cursor moving + add qword [VGA_X], 0x2 ; coord + 2 because 2 subpixels + jmp .pLoop +.pEnd: + pop rdi + pop rsi + ret +.lf: + mov rax, [VGA_HEIGHT64] + add [NextTRAM], rax ; Cursor moving + add [NextTRAM], rax + add edi, eax ; Address moving + add edi, eax + jmp .pLoop +.cr: + push rax + mov rax, qword [VGA_X] + sub qword [NextTRAM], rax ; pos = X + Y * VGA_HEIGHT64. Donc pos - X = début de ligne + sub edi, edx + mov qword [VGA_X], 0 + pop rax + jmp .pLoop +.scroll: + ; XXX ; + jmp .pLoop diff --git a/src/boot/mbr.inc b/src/boot/mbr.inc new file mode 100644 index 0000000..5e06bc9 --- /dev/null +++ b/src/boot/mbr.inc @@ -0,0 +1,160 @@ +;=----------------------------------------------------------------------------=; +; GNU GPL OS/K ; +; ; +; Authors: spectral` ; +; NeoX ; +; ; +; Desc: Bootsector for OS/K INCLUDED FUNCTIONS ; +; (x86_64 architecture only) ; +;=----------------------------------------------------------------------------=; + +read_clusters: +;---------------------------------------------------; +; Read file clusters, starting at the given cluster,; +; expects FAT to be loaded into the disk buffer. ; +; Please note that this may allocate up to 128KB ; +; of ram. ; +; ; +; Expects: AX = Starting cluster ; +; ES:DI = Location to load clusters ; +; ; +; Returns: None ; +; ; +;---------------------------------------------------; + pusha + push es + .cluster_loop: + xor bh, bh + xor dx, dx + push ax ; Get the cluster start = (cluster - 2) * sectorsPerCluster + UserData + sub ax, 2 ; Subtract 2 + mov bl, byte [sectorsPerCluster] ; Sectors per cluster is a byte value + mul bx ; multiply (cluster - 2) * sectorsPerCluster + add ax, word [UserData] ; add the UserData + xor ch, ch + mov cl, byte [sectorsPerCluster] ; Sectors to read + call read_sectors ; Read the sectors + pop ax ; Current cluster number + xor dx, dx + ;; Calculate next sector for FAT16 (cluster * 2) + mov bx, 2 ; Multiply the cluster by two (cluster is in ax) + mul bx + ;; Load sector in RAM + push ds + push si + mov si, BUFFER_SEG + mov ds, si ; Temporarly set ds:si to the FAT buffer + mov si, BUFFER_OFF + add si, ax ; Point to the next cluster in the FAT entry + mov ax, word [ds:si] ; Load ax to the next cluster in FAT + pop si + pop ds + ;; Next + cmp ax, 0xfff8 ; Check if we are at the end of the file? + jae .done + add di, 512 ; Add to the pointer offset + jnc .cluster_loop + ;; Correct the buffer because an error will occur if the buffer in memory + mov dx, es ; overlaps a 64k page boundry, when di overflows + add dh, 0x10 ; it will trigger the carry flag, so correct + mov es, dx ; extra segment by 0x1000 + jmp .cluster_loop ; Load the next file cluster + .done: + pop es + popa + ret + + +read_sectors: +;---------------------------------------------------; +; Read sectors starting at a given sector by ; +; the given times and load into a buffer. Please ; +; note that this may allocate up to 128KB of ram. ; +; ; +; Expects: AX = Starting sector ; +; CX = Number of sectors to read ; +; ES:DI = Location to load sectors ; +; ; +; Returns: None ; +; ; +;---------------------------------------------------; + pusha + push es + mov bx, di ; Convert es:di to es:bx for int 13h + .sector_loop: + push ax + push cx + xor dx, dx + div word [sectorsPerTrack] ; Divide the lba (value in ax) by sectorsPerTrack + mov cx, dx ; Save the absolute sector value + inc cx + xor dx, dx ; Divide by the number of heads + div word [heads] ; to get absolute head and track values + mov dh, dl ; Move the absolute head into dh + mov ch, al ; Low 8 bits of absolute track + shl ah, 1 ; High 2 bits of absolute track + shl ah, 1 + shl ah, 1 + shl ah, 1 + shl ah, 1 + shl ah, 1 + or cl, ah ; Now cx is set with respective track and sector numbers + mov dl, byte [Bootdrv] ; Set correct Bootdrv for int 13h + mov di, 5 ; Try five times to read the sector because i love 5 + .attempt_read: + mov ax, 0x0201 ; Read Sectors func of int 13h, read one sector + int 0x13 ; Call int 13h (BIOS disk I/O) + jnc .read_ok ; If no carry set, the sector has been read + xor ah, ah ; Reset Bootdrv func of int 13h + int 0x13 ; Call int 13h (BIOS disk I/O) + dec di ; Decrease read attempt counter + jnz .attempt_read ; Try to read the sector again + mov si, DiskError ; Error reading the disk :/ + call print + jmp reboot + .read_ok: + pop cx + pop ax + inc ax ; Increase the next sector to read + add bx, word [bytesPerSector] ; Add to the buffer address for the next sector + jnc .next_sector + ;; Fixing buffer because an error will occur if the buffer in memory + mov dx, es ; overlaps a 64k page boundry, when bx overflows + add dh, 0x10 ; it will trigger the carry flag, so correct + mov es, dx ; es segment by 0x1000 + .next_sector: + loop .sector_loop + pop es + popa + ret + +print: +;---------------------------------------------------; +; Print out a simple string. ; +; ; +; Expects: DS:SI = String to print ; +; ; +; Returns: None ; +; ; +;---------------------------------------------------; + lodsb ; Load byte from ds:si to al + or al, al ; If al is empty stop looping + jz .done ; Done looping and return + mov ah, 0x0e ; Teletype output + int 0x10 ; Video interupt + jmp print ; Loop untill string is null + .done: + ret + +reboot: + xor ax, ax + int 0x16 ; Get a single keypress + mov ah, 0x0e ; Teletype output + mov al, 0x0d ; Carriage return + int 0x10 ; Video interupt + mov al, 0x0a ; Line feed + int 0x10 ; Video interupt + mov al, 0x0a ; Line feed + int 0x10 ; Video interupt + xor ax, ax + int 0x19 ; Reboot the system