; ============================================================================= ; dmesg.asm - kernel boot spew: everything the kernel knows implicitly before ; init spawns, printed dmesg-style on the LCD console (and mirrored over the ; link port, so a gbhub logs the whole boot). ; ; The info costs nothing to know: ; - the boot ROM hands the console model in A/B at entry (saved to wBootA/B) ; - the cartridge describes itself in its own header ($0147-$0149) ; - the CGB memory map is a constant of the hardware ; - subsystem shapes (proc slots, sockets, program table) are link-time facts ; - fs_init just mounted (or formatted) the disk and left the block bitmap ; in fs_bmbuf - counting free blocks is a 16-byte popcount ; ============================================================================= INCLUDE "include/gbos.inc" SECTION "dmesg", ROM0 ; ----------------------------------------------------------------------------- ; kernel console output (boot-time: no process context, so KPutc is unusable) ; ----------------------------------------------------------------------------- ; kputc(A = char) - LCD terminal + serial mirror. Preserves BC/DE/HL. kputc:: push bc push de push hl ld b, a ld [rSB], a ; mirror to the link (gbhub console log) ld a, $81 ld [rSC], a ld a, b call term_putc pop hl pop de pop bc ret ; kputs(HL = NUL-terminated string). Clobbers A, HL. kputs:: .l ld a, [hl+] or a ret z call kputc jr .l ; kputhex(A = byte) - two uppercase hex digits. Clobbers A. kputhex:: push af swap a call .nib pop af .nib and $0F add "0" cp "9" + 1 jr c, .put add "A" - "9" - 1 .put jp kputc ; kputdec(A = 0..255) - decimal, no leading zeros. Clobbers A, BC, DE. kputdec:: ld c, 0 ; "printed a digit yet" flag ld b, 100 call .digit ld b, 10 call .digit add "0" jp kputc ; ones digit always prints .digit ; A/B -> A = remainder; prints quotient digit ld e, 0 .sub cp b jr c, .rem sub b inc e jr .sub .rem ld d, a ld a, e or c jr z, .skip ; leading zero ld a, e add "0" call kputc ld c, 1 .skip ld a, d ret ; ----------------------------------------------------------------------------- ; boot_banner - kernel line + console model + cart header + memory map + proc ; shape. Called right after term_init. ; ----------------------------------------------------------------------------- boot_banner:: ld hl, .s_kernel call kputs ; console model: boot ROM leaves A=$11 (CGB/AGB, B bit0 = AGB), $01 (DMG), ; $FF (MGB/pocket) ld hl, .s_console call kputs ld a, [wBootA] cp $11 jr nz, .not_cgb ld a, [wBootB] bit 0, a jr z, .cgb ld hl, .s_agb jr .model .cgb ld hl, .s_cgb jr .model .not_cgb cp $01 jr nz, .not_dmg ld hl, .s_dmg jr .model .not_dmg ld hl, .s_mgb .model call kputs ld hl, .s_boota call kputs ld a, [wBootA] call kputhex ld a, ")" call kputc ld a, 10 call kputc ; cart: the header describes the very cartridge we run from ld hl, .s_cart call kputs ld a, [$0147] ; cart type cp $19 jr c, .rawtype cp $1F jr nc, .rawtype ld hl, .s_mbc5 call kputs jr .romsize .rawtype ld hl, .s_type call kputs ld a, [$0147] call kputhex .romsize ld hl, .s_rom call kputs ld a, [$0148] ; ROM size code: 32K << code cp 9 jr nc, .romq add a ; *2: word index into the pointer table ld e, a ld d, 0 ld hl, .romtab add hl, de ld a, [hl+] ld h, [hl] ld l, a jr .romp .romq ld hl, .s_unk .romp call kputs ld hl, .s_sram call kputs ld a, [$0149] ; cart RAM size code cp 6 jr nc, .ramq add a ld e, a ld d, 0 ld hl, .ramtab add hl, de ld a, [hl+] ld h, [hl] ld l, a jr .ramp .ramq ld hl, .s_unk .ramp call kputs ld hl, .s_sram2 call kputs ; memory map: hardware constants of the CGB ld hl, .s_mem call kputs ; processes + programs: link-time shape of the kernel ld hl, .s_proc call kputs ld hl, ProgramTableEnd - ProgramTable ; bytes; 4 per entry ld a, l srl h rra srl h rra ; /4 (table < 1K, fits in A) call kputdec ld hl, .s_progs call kputs ret .s_kernel: db "gbos sm83 microkernel\n", 0 .s_console: db "console: ", 0 .s_cgb: db "CGB", 0 .s_agb: db "AGB", 0 .s_dmg: db "DMG", 0 .s_mgb: db "MGB", 0 .s_boota: db " (boot a=$", 0 .s_cart: db "cart: ", 0 .s_mbc5: db "mbc5", 0 .s_type: db "type $", 0 .s_rom: db ", ", 0 .s_sram: db " rom, ", 0 .s_sram2: db " sram\n", 0 .s_unk: db "?", 0 .s_mem: db "mem: 32K wram 16K vram 127B hram\n", 0 .s_proc: db "proc: {d:MAX_PROCS} slots, ", 0 .s_progs: db " programs\n", 0 .romtab: dw .r0, .r1, .r2, .r3, .r4, .r5, .r6, .r7, .r8 .r0: db "32K",0 .r1: db "64K",0 .r2: db "128K",0 .r3: db "256K",0 .r4: db "512K",0 .r5: db "1M",0 .r6: db "2M",0 .r7: db "4M",0 .r8: db "8M",0 .ramtab: dw .m0, .m1, .m2, .m3, .m4, .m5 .m0: db "no",0 .m1: db "2K",0 .m2: db "8K",0 .m3: db "32K",0 .m4: db "128K",0 .m5: db "64K",0 ; ----------------------------------------------------------------------------- ; boot_net - after net_init: the link is the network. ; ----------------------------------------------------------------------------- boot_net:: ld hl, .s call kputs ret .s: db "net: slip on link port, {d:MAX_SOCKS} sockets\n", 0 ; ----------------------------------------------------------------------------- ; boot_fs - after fs_init: mounted vs freshly formatted, and free blocks ; (popcount of clear bits in the block bitmap fs_init left in fs_bmbuf). ; ----------------------------------------------------------------------------- boot_fs:: ld hl, .s_fs call kputs ld a, [wBootFsFresh] or a jr z, .mounted ld hl, .s_fresh call kputs jr .count .mounted ld hl, .s_mount call kputs .count ld hl, fs_bmbuf ld b, FS_NBLOCKS / 8 ld c, 0 ; free-block count .byte ld a, [hl+] cpl ; set bits = free blocks ld e, 8 .bit rra jr nc, .nofree inc c .nofree dec e jr nz, .bit dec b jr nz, .byte ld a, c call kputdec ld hl, .s_of call kputs ld a, FS_NBLOCKS call kputdec ld hl, .s_blkfree call kputs ret .s_fs: db "fs: gbfs v{d:FS_VERSION} ", 0 .s_mount: db "mounted, ", 0 .s_fresh: db "formatted, ", 0 .s_of: db "/", 0 .s_blkfree: db " blk free\n", 0 ; ----------------------------------------------------------------------------- ; boot_tty / boot_init - console shape, and the handoff line. ; ----------------------------------------------------------------------------- boot_tty:: ld hl, .s call kputs ret .s: db "tty: 40x18 console, SELECT = osk\n", 0 boot_init:: ld hl, .s call kputs ret .s: db "init: spawning pid 1\n", 0