diff --git a/build.sh b/build.sh index c1a706f..18ccc1c 100755 --- a/build.sh +++ b/build.sh @@ -4,8 +4,9 @@ mkdir -p bin cd src -nasm -DBIOS=1 pure64.asm -o ../bin/pure64-bios.sys -l ../bin/pure64-bios-debug.txt -nasm -DUEFI=1 pure64.asm -o ../bin/pure64-uefi.sys -l ../bin/pure64-uefi-debug.txt +nasm -dBIOS=1 -dNOVIDEO=1 pure64.asm -o ../bin/pure64-bios-novideo.sys -l ../bin/pure64-bios-novideo-debug.txt +nasm -dBIOS=1 pure64.asm -o ../bin/pure64-bios.sys -l ../bin/pure64-bios-debug.txt +nasm -dUEFI=1 pure64.asm -o ../bin/pure64-uefi.sys -l ../bin/pure64-uefi-debug.txt cd boot @@ -13,5 +14,6 @@ nasm bios.asm -o ../../bin/bios.sys -l ../../bin/bios-debug.txt nasm uefi.asm -o ../../bin/uefi.sys -l ../../bin/uefi-debug.txt nasm bios-floppy.asm -o ../../bin/bios-floppy.sys -l ../../bin/bios-floppy-debug.txt nasm bios-pxe.asm -o ../../bin/bios-pxe.sys -l ../../bin/bios-pxe-debug.txt +nasm bios-novideo.asm -o ../../bin/bios-novideo.sys -l ../../bin/bios-novideo-debug.txt cd ../.. diff --git a/docs/Boot Process.md b/docs/Boot Process.md index 266500c..da30515 100644 --- a/docs/Boot Process.md +++ b/docs/Boot Process.md @@ -5,7 +5,7 @@ Pure64 uses two different first stage loaders depending on the firmware of the s * BIOS loads the first 512-byte sector from the boot disk to `0x7C00` * The boot code pulls some data about the system (memory map), sets the video mode, and loads the second stage loader to `0x8000`. * The boot code transitions from 16-bit real mode to 32-bit protected mode and then jumps to the second stage. -* The second stage immediately transitions from 32-bit protected mode to a minimal 64-bit long mode. It then follows unified boot path. +* The second stage immediately transitions from 32-bit protected mode to a minimal 64-bit long mode. It then follows the unified boot path. ## UEFI boot (`uefi.asm`): * UEFI loads `\EFI\BOOT\BOOTX64.EFI` from the FAT32 partition of the boot disk. @@ -13,7 +13,7 @@ Pure64 uses two different first stage loaders depending on the firmware of the s * The second stage then follows the unified boot process as the system is already in 64-bit mode. ## Unified boot with the second stage (`pure64.asm`): -* Once it 64-bit mode it configures the PIC, PIT, serial port, sets up the proper 64-bit environment. +* Once in 64-bit mode it configures the PIC, PIT, serial port, sets up the proper 64-bit environment. * Patches the second stage loader so that the AP's can start at `0x8000` as well. * The software processes the system memory map and creates a list of memory that is usable. * All available memory above 4MiB is mapped to `0xFFFF800000000000` diff --git a/docs/README.md b/docs/README.md index 9ebf6b0..20bbcf8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -122,9 +122,7 @@ All Pure64 binaries are in the `bin` directory. ### BIOS -After creating a kernel this is a possible routine to create a bootable image. -The commands require Pure64 to be build and `pure64.sys` and `mbr.sys` to be in the same directory -as your kernel with the name `kernel.bin` +For BIOS systems you'll need `pure64-bios.sys` and `mbr.sys` to be in the same directory as your kernel with the name `kernel.bin` ``` dd if=/dev/zero of=disk.img count=128 bs=1048576 diff --git a/src/boot/bios-novideo.asm b/src/boot/bios-novideo.asm new file mode 100644 index 0000000..d2fb4b3 --- /dev/null +++ b/src/boot/bios-novideo.asm @@ -0,0 +1,248 @@ +; ============================================================================= +; Pure64 MBR -- a 64-bit OS/software loader written in Assembly for x86-64 systems +; Copyright (C) 2008-2025 Return Infinity -- see LICENSE.TXT +; +; This Master Boot Record will load Pure64 from a pre-defined location on the +; hard drive without making use of the file system. +; +; In this code we are expecting a BMFS-formatted drive. With BMFS the Pure64 +; binary is required to start at sector 16 (8192 bytes from the start). A small +; check is made to make sure Pure64 was loaded by comparing a signature. +; ============================================================================= + +; Default location of the second stage boot loader. This loads +; 32 KiB from sector 16 into memory at 0x8000 +%define DAP_SECTORS 64 +%define DAP_STARTSECTOR 16 +%define DAP_ADDRESS 0x8000 +%define DAP_SEGMENT 0x0000 + +BITS 16 +org 0x7C00 + +entry: + jmp bootcode ; Jump past the BPB data + nop + +; BPB (BIOS Parameter Block) +dq 0 ; OEM identifier +dw 0 ; Bytes per sector +db 0 ; Sectors per cluster +dw 0 ; Reserved sectors +db 0 ; Number of FATs +dw 0 ; Number of root directory entries +dw 0 ; The total sectors in the logical volume +db 0 ; Media descriptor type +dw 0 ; Number of sectors per FAT +dw 0 ; Number of sectors per track +dw 0 ; Number of heads or sides on the storage media +dd 0 ; Number of hidden sectors +dd 0 ; Large sector count + +; EBPB (Extended Boot Record) +dd 0 ; Sectors per FAT +dw 0 ; Flags +dw 0 ; FAT version number +dd 0 ; The cluster number of the root directory +dw 0 ; The sector number of the FSInfo structure +dw 0 ; The sector number of the backup boot sector +dq 0 ; Reserved +dd 0 ; Reserved +db 0 ; Drive number +db 0 ; Flags in Windows NT +db 0 ; Signature +dd 0 ; Volume ID 'Serial' number +times 11 db 0 ; Volume label string +dq 0 ; System identifier string. Always "FAT32 " + +bootcode: + cli ; Disable interrupts + cld ; Clear direction flag + xor eax, eax + mov ss, ax + mov es, ax + mov ds, ax + mov sp, 0x7C00 + sti ; Enable interrupts + + mov [DriveNumber], dl ; BIOS passes drive number in DL + + ; Configure first serial port + mov dx, 0 ; Port + mov ax, 0x00E3 ; Init port, 9600bps 8N1 + int 0x14 + + ; Output message to serial + mov si, msg_Load + call output_serial + +; Get the BIOS E820 Memory Map +; https://wiki.osdev.org/Detecting_Memory_(x86)#BIOS_Function:_INT_0x15,_EAX_=_0xE820 +; The code below is from https://wiki.osdev.org/Detecting_Memory_(x86)#Getting_an_E820_Memory_Map +; inputs: es:di -> destination buffer for 24 byte entries +; outputs: bp = entry count, trashes all registers except esi +; The function below creates a memory map at address 0x6000 and the records are: +; 64-bit Base +; 64-bit Length +; 32-bit Type (1 = normal, 2 reserved, ACPI reclaimable) +; 32-bit ACPI +; 64-bit Padding +do_e820: + mov edi, 0x00006000 ; location that memory map will be stored to + xor ebx, ebx ; ebx must be 0 to start + xor bp, bp ; keep an entry count in bp + mov edx, 0x0534D4150 ; Place "SMAP" into edx + mov eax, 0xe820 + mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry + mov ecx, 24 ; ask for 24 bytes + int 0x15 + jc nomemmap ; carry set on first call means "unsupported function" + mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register? + cmp eax, edx ; on success, eax must have been reset to "SMAP" + jne nomemmap + test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless) + je nomemmap + jmp jmpin +e820lp: + mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call + mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry + mov ecx, 24 ; ask for 24 bytes again + int 0x15 + jc memmapend ; carry set means "end of list already reached" + mov edx, 0x0534D4150 ; repair potentially trashed register +jmpin: + jcxz skipent ; skip any 0 length entries + cmp cl, 20 ; got a 24 byte ACPI 3.X response? + jbe notext + test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear? + je skipent +notext: + mov ecx, [es:di + 8] ; get lower dword of memory region length + test ecx, ecx ; is the qword == 0? + jne goodent + mov ecx, [es:di + 12] ; get upper dword of memory region length + jecxz skipent ; if length qword is 0, skip entry +goodent: + inc bp ; got a good entry: ++count, move to next storage spot + add di, 32 ; Pad to 32 bytes for each record +skipent: + test ebx, ebx ; if ebx resets to 0, list is complete + jne e820lp +nomemmap: +memmapend: + xor eax, eax ; Create a blank record for termination (32 bytes) + mov ecx, 8 + rep stosd + +; Enable the A20 gate +set_A20: + in al, 0x64 + test al, 0x02 + jnz set_A20 + mov al, 0xD1 + out 0x64, al +check_A20: + in al, 0x64 + test al, 0x02 + jnz check_A20 + mov al, 0xDF + out 0x60, al + + ; Video modes aren't supported in this boot sector + ; Clear the video detail memory for Pure64 + mov edi, 0x5F00 + xor eax, eax + mov ecx, 64 + rep stosd + + ; Read the 2nd stage boot loader into memory. + mov ah, 0x42 ; Extended Read + mov dl, [DriveNumber] ; http://www.ctyme.com/intr/rb-0708.htm + mov si, DAP + int 0x13 + jc halt + + ; Check signature +; mov eax, [0x8000] +; cmp eax, 0x00017EE9 ; Match against the Pure64 binary +; jne halt + + ; Output message to serial + mov si, msg_Ok + call output_serial + + mov bl, 'B' ; 'B' as we booted via BIOS + + ; At this point we are done with real mode and BIOS interrupts. Jump to 32-bit mode. + cli ; No more interrupts + lgdt [cs:GDTR32] ; Load GDT register + mov eax, cr0 + or al, 0x01 ; Set protected mode bit + mov cr0, eax + jmp 8:0x8000 ; Jump to 32-bit protected mode + +;magic_fail: +; mov si, msg_Error +; call output_serial +halt: + hlt + jmp halt +;------------------------------------------------------------------------------ + + +;------------------------------------------------------------------------------ +; Output a string via serial +; IN: SI - Address of start of string +output_serial: ; Output string via serial + pusha +output_serial_next_char: + mov dx, 0 ; First serial port + mov ah, 0x01 ; SERIAL - WRITE CHARACTER TO PORT + lodsb ; Get char from string + cmp al, 0 + je output_serial_done ; If char is zero, end of string + int 0x14 ; Otherwise, output it + jmp short output_serial_next_char +output_serial_done: + popa + ret +;------------------------------------------------------------------------------ + +msg_Load db "MBR ", 0 +msg_Ok db "OK", 0 +msg_Error db "Error!", 0 + +align 16 +GDTR32: ; Global Descriptors Table Register +dw gdt32_end - gdt32 - 1 ; limit of GDT (size minus one) +dq gdt32 ; linear address of GDT + +align 16 +gdt32: +dw 0x0000, 0x0000, 0x0000, 0x0000 ; Null descriptor +dw 0xFFFF, 0x0000, 0x9A00, 0x00CF ; 32-bit code descriptor +dw 0xFFFF, 0x0000, 0x9200, 0x00CF ; 32-bit data descriptor +gdt32_end: + +align 4 + +DAP: +db 0x10 +db 0x00 +dw DAP_SECTORS +dw DAP_ADDRESS +dw DAP_SEGMENT +dq DAP_STARTSECTOR + +DriveNumber db 0x00 + +times 446-$+$$ db 0 + +; Partition entries (4x 16-bytes) + +times 510-$+$$ db 0 + +dw 0xAA55 ; Boot signature + + +; EOF diff --git a/src/fdc/fdc_64.asm b/src/fdc/fdc_64.asm index 2dacecd..c166dc5 100644 --- a/src/fdc/fdc_64.asm +++ b/src/fdc/fdc_64.asm @@ -420,4 +420,3 @@ mem_buff dd MEM_BUFF ; ============================================================================= ; EOF - diff --git a/src/init/acpi.asm b/src/init/acpi.asm index c703a75..460fe71 100644 --- a/src/init/acpi.asm +++ b/src/init/acpi.asm @@ -154,12 +154,14 @@ init_smp_acpi_done: noACPI: novalidacpi: +%ifndef NOVIDEO ; Set screen to Teal mov rdi, [0x00005F00] ; Frame buffer base mov rcx, [0x00005F08] ; Frame buffer size shr rcx, 2 ; Quick divide by 4 mov eax, 0x0000FFFF ; 0x00RRGGBB rep stosd +%endif jmp $ diff --git a/src/init/hpet.asm b/src/init/hpet.asm index 1cfa1c9..c5eb377 100644 --- a/src/init/hpet.asm +++ b/src/init/hpet.asm @@ -60,7 +60,6 @@ os_hpet_init_disable_int: os_hpet_init_error: ret -; ----------------------------------------------------------------------------- ; ----------------------------------------------------------------------------- @@ -155,4 +154,4 @@ HPET_TIMER_2_INT equ 0x150 ; ============================================================================= -; EOF \ No newline at end of file +; EOF diff --git a/src/init/serial.asm b/src/init/serial.asm new file mode 100644 index 0000000..b784e2a --- /dev/null +++ b/src/init/serial.asm @@ -0,0 +1,65 @@ +; ============================================================================= +; Pure64 -- a 64-bit OS/software loader written in Assembly for x86-64 systems +; Copyright (C) 2008-2025 Return Infinity -- see LICENSE.TXT +; +; INIT SERIAL - 115200 bps, 8N1 (8 data bits, no parity, and 1 stop bit) +; ============================================================================= + + +init_serial: + ; Disable Interrupts + mov dx, COM_PORT_INTERRUPT_ENABLE + mov al, 0 ; Disable all interrupts + out dx, al + + ; Enable divisor register for setting baud rate + mov dx, COM_PORT_LINE_CONTROL + mov dl, 0x80 ; DLB (7 set) + out dx, al + + ; Send the divisor (baud rate will be 115200 / divisor) + mov dx, COM_PORT_DATA + mov ax, BAUD_115200 + out dx, al + mov dx, COM_PORT_DATA+1 + shr ax, 8 + out dx, al + + ; Disable divisor register and set values + mov dx, COM_PORT_LINE_CONTROL + mov al, 00000111b ; 8 data bits (0-1 set), one stop bit (2 set), no parity (3-5 clear), DLB (7 clear) + out dx, al + + ; Disable modem control + mov dx, COM_PORT_MODEM_CONTROL + mov al, 0 + out dx, al + + ; Set FIFO + mov dx, COM_PORT_FIFO_CONTROL + mov al, 0xC7 ; Enable FIFO, clear them, 14-byte threshold + out dx, al + + ret + + +; Port Registers +COM_BASE equ 0x3F8 +COM_PORT_DATA equ COM_BASE + 0 +COM_PORT_INTERRUPT_ENABLE equ COM_BASE + 1 +COM_PORT_FIFO_CONTROL equ COM_BASE + 2 +COM_PORT_LINE_CONTROL equ COM_BASE + 3 +COM_PORT_MODEM_CONTROL equ COM_BASE + 4 +COM_PORT_LINE_STATUS equ COM_BASE + 5 +COM_PORT_MODEM_STATUS equ COM_BASE + 6 +COM_PORT_SCRATCH_REGISTER equ COM_BASE + 7 + +; Baud Rates +BAUD_115200 equ 1 +BAUD_57600 equ 2 +BAUD_9600 equ 12 +BAUD_300 equ 384 + + +; ============================================================================= +; EOF diff --git a/src/init/smp.asm b/src/init/smp.asm index 47f626a..900905d 100644 --- a/src/init/smp.asm +++ b/src/init/smp.asm @@ -7,6 +7,8 @@ init_smp: + sti ; Enable interrupts in case PIT is needed + ; Check if we want the AP's to be enabled.. if not then skip to end cmp byte [cfg_smpinit], 1 ; Check if SMP should be enabled jne noMP ; If not then skip SMP init @@ -50,7 +52,7 @@ smp_send_INIT_done: ; Wait 500 microseconds mov eax, 500 - call os_hpet_delay + call delay mov esi, IM_DetectedCoreIDs xor ecx, ecx @@ -82,7 +84,7 @@ smp_send_SIPI_done: ; Wait 10000 microseconds for the AP's to finish mov eax, 10000 - call os_hpet_delay + call delay noMP: ; Gather and store the APIC ID of the BSP @@ -100,7 +102,7 @@ noMP: rdtsc push rax mov rax, 1024 - call os_hpet_delay + call delay rdtsc pop rdx sub rax, rdx @@ -109,7 +111,28 @@ noMP: div rcx mov [p_cpu_speed], ax + cli ; Disable interrupts in case PIT was needed + + ret + + +; ----------------------------------------------------------------------------- +; delay -- Delay by X microseconds +; IN: RAX = Time microseconds +; OUT: All registers preserved +; Note: There are 1,000,000 microseconds in a second +; There are 1,000 milliseconds in a second +delay: + push rax + push rbx + + call os_hpet_delay + +delay_done: + pop rbx + pop rax ret +; ----------------------------------------------------------------------------- ; ============================================================================= diff --git a/src/interrupt.asm b/src/interrupt.asm index e313d4b..98ca411 100644 --- a/src/interrupt.asm +++ b/src/interrupt.asm @@ -144,12 +144,14 @@ exception_gate_21: jmp exception_gate_main exception_gate_main: +%ifndef NOVIDEO ; Set screen to Red mov rdi, [0x00005F00] ; Frame buffer base mov rcx, [0x00005F08] ; Frame buffer size shr rcx, 2 ; Quick divide by 4 mov eax, 0x00FF0000 ; 0x00RRGGBB rep stosd +%endif exception_gate_main_hang: hlt jmp exception_gate_main_hang ; Hang. User must reset machine at this point diff --git a/src/pure64.asm b/src/pure64.asm index fcbd087..c0f1e3b 100644 --- a/src/pure64.asm +++ b/src/pure64.asm @@ -76,6 +76,7 @@ bootmode: xor ebp, ebp mov esp, 0x8000 ; Set a known free location for the stack +%ifndef NOVIDEO ; Save the frame buffer address, size (after its calculated), and the screen x,y xor eax, eax xor ebx, ebx @@ -106,6 +107,7 @@ bootmode: stosw ; PixelsPerScanLine mov eax, 32 stosw ; BitsPerPixel +%endif ; Clear memory for the Page Descriptor Entries (0x10000 - 0x5FFFF) mov edi, 0x00210000 @@ -244,6 +246,7 @@ start64: mov al, 0x00 out 0x40, al +%ifndef NOVIDEO ; Clear screen xor eax, eax xor ecx, ecx @@ -255,10 +258,32 @@ start64: mov rdi, [0x00005F00] mov eax, 0x00404040 rep stosd +%endif +%ifndef NOVIDEO ; Visual Debug (1/8) mov ebx, 0 call debug_block +%endif + + ; Configure serial port @ 0x03F8 as 115200 8N1 + call init_serial + + mov rsi, msg_pure64 ; Output "[ Pure64 ]" + call debug_msg + + ; Output boot method + mov rsi, msg_boot + call debug_msg + cmp byte [p_BootMode], 'U' + je boot_uefi + mov rsi, msg_bios + call debug_msg + jmp msg_boot_done +boot_uefi: + mov rsi, msg_uefi + call debug_msg +msg_boot_done: ; Clear out the first 20KiB of memory. This will store the 64-bit IDT, GDT, PML4, PDP Low, and PDP High mov ecx, 5120 @@ -395,9 +420,11 @@ clearcs64: lgdt [GDTR64] ; Reload the GDT +%ifndef NOVIDEO ; Visual Debug (2/8) mov ebx, 2 call debug_block +%endif ; Build the IDT xor edi, edi ; create the 64-bit IDT (at linear address 0x0000000000000000) @@ -712,29 +739,54 @@ pde_end: and cl, 1 mov byte [p_x2APIC], cl +%ifndef NOVIDEO ; Visual Debug (3/8) mov ebx, 4 call debug_block +%endif + mov rsi, msg_acpi + call debug_msg call init_acpi ; Find and process the ACPI tables + mov rsi, msg_ok + call debug_msg +%ifndef NOVIDEO ; Visual Debug (4/8) mov ebx, 6 call debug_block +%endif + mov rsi, msg_bsp + call debug_msg call init_cpu ; Configure the BSP CPU + mov rsi, msg_ok + call debug_msg +%ifndef NOVIDEO ; Visual Debug (5/8) mov ebx, 8 call debug_block - +%endif + +; Configure system timer + mov rsi, msg_hpet + call debug_msg call init_hpet ; Configure the HPET + mov rsi, msg_ok + call debug_msg +%ifndef NOVIDEO ; Visual Debug (6/8) mov ebx, 10 call debug_block +%endif + mov rsi, msg_smp + call debug_msg call init_smp ; Init of SMP, deactivate interrupts + mov rsi, msg_ok + call debug_msg ; Reset the stack to the proper location (was set to 0x8000 previously) mov rsi, [p_LocalAPICAddress] ; We would call p_smp_get_id here but the stack is not ... @@ -825,6 +877,7 @@ no_address_size: mov al, [p_x2APIC] stosb +%ifndef NOVIDEO ; Visual Debug (7/8) mov ebx, 12 call debug_block @@ -876,6 +929,7 @@ lfb_wc_end: mov rax, cr3 ; Flush TLB mov cr3, rax wbinvd ; Flush Cache +%endif ; Move the trailing binary to its final location mov esi, 0x8000+PURE64SIZE ; Memory offset to end of pure64.sys @@ -883,9 +937,14 @@ lfb_wc_end: mov ecx, ((32768 - PURE64SIZE) / 8) rep movsq ; Copy 8 bytes at a time +%ifndef NOVIDEO ; Visual Debug (8/8) mov ebx, 14 call debug_block +%endif + + mov rsi, msg_kernel + call debug_msg %ifdef BIOS cmp byte [p_BootDisk], 'F' ; Check if sys is booted from floppy? @@ -916,6 +975,7 @@ clear_regs: %include "init/acpi.asm" %include "init/cpu.asm" %include "init/hpet.asm" +%include "init/serial.asm" %include "init/smp.asm" %ifdef BIOS %include "fdc/dma.asm" @@ -925,6 +985,7 @@ clear_regs: %include "sysvar.asm" +%ifndef NOVIDEO ; ----------------------------------------------------------------------------- ; debug_block - Create a block of colour on the screen ; IN: EBX = Index # @@ -981,7 +1042,7 @@ nextline: pop rax ret ; ----------------------------------------------------------------------------- - +%endif %ifdef BIOS ; ----------------------------------------------------------------------------- @@ -1010,6 +1071,106 @@ debug_progressbar: %endif +; ----------------------------------------------------------------------------- +; debug_msg_char - Send a single char via the serial port +; IN: AL = Byte to send +debug_msg_char: + pushf + push rdx + push rax ; Save the byte + mov dx, 0x03F8 ; Address of first serial port +debug_msg_char_wait: + add dx, 5 ; Offset to Line Status Register + in al, dx + sub dx, 5 ; Back to to base + and al, 0x20 + cmp al, 0 + je debug_msg_char_wait + pop rax ; Restore the byte + out dx, al ; Send the char to the serial port +debug_msg_char_done: + pop rdx + popf + ret +; ----------------------------------------------------------------------------- + + +; ----------------------------------------------------------------------------- +; debug_msg_char - Send a message via the serial port +; IN: RSI = Location of message +debug_msg: + pushf + push rdx + push rax + cld ; Clear the direction flag.. we want to increment through the string + mov dx, 0x03F8 ; Address of first serial port +debug_msg_next: + add dx, 5 ; Offset to Line Status Register + in al, dx + sub dx, 5 ; Back to to base + and al, 0x20 + cmp al, 0 + je debug_msg_next + lodsb ; Get char from string and store in AL + cmp al, 0 + je debug_msg_done + out dx, al ; Send the char to the serial port + jmp debug_msg_next +debug_msg_done: + pop rax + pop rdx + popf + ret +; ----------------------------------------------------------------------------- + + +; ----------------------------------------------------------------------------- +; debug_dump_(rax|eax|ax|al) -- Dump content of RAX, EAX, AX, or AL +; IN: RAX/EAX/AX/AL = content to dump +; OUT: Nothing, all registers preserved +debug_dump_rax: + rol rax, 8 + call debug_dump_al + rol rax, 8 + call debug_dump_al + rol rax, 8 + call debug_dump_al + rol rax, 8 + call debug_dump_al + rol rax, 32 +debug_dump_eax: ; RAX is used here instead of EAX to preserve the upper 32-bits + rol rax, 40 + call debug_dump_al + rol rax, 8 + call debug_dump_al + rol rax, 16 +debug_dump_ax: + rol ax, 8 + call debug_dump_al + rol ax, 8 +debug_dump_al: + push rax ; Save RAX + push ax ; Save AX for the low nibble + shr al, 4 ; Shift the high 4 bits into the low 4, high bits cleared + or al, '0' ; Add "0" + cmp al, '9'+1 ; Digit? + jl debug_dump_al_h ; Yes, store it + add al, 7 ; Add offset for character "A" +debug_dump_al_h: + call debug_msg_char + pop ax ; Restore AX + and al, 0x0F ; Keep only the low 4 bits + or al, '0' ; Add "0" + cmp al, '9'+1 ; Digit? + jl debug_dump_al_l ; Yes, store it + add al, 7 ; Add offset for character "A" +debug_dump_al_l: + call debug_msg_char + pop rax ; Restore RAX + ret +; ----------------------------------------------------------------------------- + + EOF: db 0xDE, 0xAD, 0xC0, 0xDE diff --git a/src/sysvar.asm b/src/sysvar.asm index e77dceb..9cdf5ef 100644 --- a/src/sysvar.asm +++ b/src/sysvar.asm @@ -6,6 +6,22 @@ ; ============================================================================= +; Messages +msg_pure64: db 13, 10, 13, 10, '[ Pure64 ]', 0 +msg_ok: db 'ok', 0 +msg_error: db 'ERROR', 0 +msg_exception: db 'EXCEPTION 0x', 0 +msg_pml4: db 13, 10, 'pml4 ', 0 +msg_boot: db 13, 10, 'boot ', 0 +msg_bios: db 'bios', 0 +msg_uefi: db 'uefi', 0 +msg_acpi: db 13, 10, 'acpi ', 0 +msg_bsp: db 13, 10, 'bsp ', 0 +msg_hpet: db 13, 10, 'hpet ', 0 +msg_pit: db 13, 10, 'pit ', 0 +msg_smp: db 13, 10, 'smp ', 0 +msg_kernel: db 13, 10, 'kernel start', 13, 10, 0 + ;CONFIG cfg_smpinit: db 1 ; By default SMP is enabled. Set to 0 to disable.