From 16331682118d3db57065fac53e324cc3038de4d1 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 5 Jan 2019 21:55:58 +0000 Subject: [PATCH] sc114: make loader use generic filo parts --- Kernel/platform-sc114/loader.s | 390 ++------------------------------- 1 file changed, 23 insertions(+), 367 deletions(-) diff --git a/Kernel/platform-sc114/loader.s b/Kernel/platform-sc114/loader.s index 569bfeb8..336c6a7c 100644 --- a/Kernel/platform-sc114/loader.s +++ b/Kernel/platform-sc114/loader.s @@ -1,6 +1,6 @@ ; -; We have 12K loaded D000-FFFF. We actually keep ourselves highish up -; to leave lots of room to load code +; This will need our own SCM module as well because the CP/M loader +; moves CP/M and trashes SCM before running it. ; ; Currently this and the glue driver code is well under 2 disk blocks. ; Adding partitions should still fit 2 blocks nicely. @@ -18,375 +18,15 @@ FILETYPE .equ 0x80 .area _CODE ; -; The main loop. We wait for about 2 seconds looking for input. If we -; see input then we go to command line mode, if not we load the -; default image name. If the default fails we then drop into command -; line mode. +; Magic for the loader ; -; Right now we treat anything as a filename, except * which indicates -; platform specific helpers. We may add other commands later (eg -; single letters to switch drive). -; -boot_begin: - ; Run anything system specific - call preboot - ld hl,#filo - call con_write - ; Load the partition table and find our partition - call partitions -boot_up: - ld hl,#prompt - call con_write - ld b,#200 ; 2 seconds -boot_wait: - push bc - call con_check - jr nz, con_prompt - call delay10ms - pop bc - djnz boot_wait -boot_default: - ld hl,#newline - call con_write - ld hl,#defname -boot_name: - ld de,#loadname - ld bc,#31 - ldir - call load_kernel - ld hl,#failed - call con_write -con_next: - ld hl,#prompt - call con_write -con_prompt: - call con_readbuf - jr z, con_next - ld a,(hl) - cp #'*' - jr nz, boot_name - call system - jr con_next + .byte 'Z' + .byte 80 -prompt: - .asciz 'FILO: ' -failed: - .ascii 'Load failed.' -newline: - .asciz '\n' -defname: - .asciz 'fuzix' -filo: - .ascii 'Fuzix Intermediate Loader v0.01.\n' - .asciz '(C)2019 Alan Cox\n\n' - - .area _DATA - -loadname: - .ds 31 -ibuf: - .ds 64 -dbuf: - .ds 512 -partbase_l: - .dw 0 -partbase_h: - .dw 0 - - .area _CODE - -partitions: - ; No partitions found (hack for now) - ld hl,#0 - ld (partbase_l),hl - ld (partbase_h),hl - ret -; -; We have set the base according to the partition table, work relative -; to it -; -; The key to this being small is that a directory is a special kind of -; file. We therefore only need one routine which loads a file at the -; load address to do all the work. We load inode 1 (/) and find the -; file, then we use the same function to load the actual file. ; -; We could easily add subdirectories if we wanted. +; Loader core ; -; The data loading is kept compact by having a routine to load an -; array of block numbers. That same logic works for both the direct -; blocks and the first indirect (which is all we care about). -; -load_kernel: - ; - ; Load the super block - ; - ld de,#1 ; 0 is the boot block space, 1 the superblock - ld hl,#dbuf - call bread - ret nz - ; - ; Check the superblock is valid - ; - ld hl,(dbuf) - ld de,#12742 ; file system - or a - sbc hl,de - ret nz ; not valid - ; - ; It's a filesystem so we can load inode 1 - ; - ld hl,#1 - ld a,#DIRTYPE ; want a directory - - call loadi ; load / into memory - ; returns DE = size - ret nz ; / failed to load or too large - ld ix,#loadbuf ; start pointer into IX - ; - ; Turn the size into a record count of 32 byte records - ; - ld b,#5 -shift5: - srl d - srl e - djnz shift5 - ; DE is now record count - - ; - ; Scan the loaded file (directory) for the wanted name entry - ; -find_by_name: - push de - ld hl,#loadname - push ix - call cmpname - pop ix - jr nz, next_name - ld l,30(ix) - ld h,31(ix) - ld a,h ; empty slot even if matched - or l - jr nz, found_name -next_name: - ; - ; Move on a record - ; - ld de,#32 - add ix,de - pop de - dec de - ld a,d - or e - jr nz, find_by_name - ; - ; Not found - ; - inc a ; force NZ - ret ; not found - ; - ; Name match found - ; -found_name: - pop af ; Discard top of stack - ld a,#FILETYPE ; must be a file - call loadi ; replace the directory load with the target - ret nz - ; - ; And launch - ; - jp loadbuf - -; -; Load a file or directory if not too big -; -loadi: - ; A is the required type, HL the inode - call iget ; get the relevant inode into the ibuf - ret nz - ld de, (ibuf+I_SIZE+2) - ld a,d - or e - ret nz ; over 64K - ld de, (ibuf+I_SIZE) - ld a,#0xE0 - cp d - jr nc, retnz ; too big too load - - ld a,e - or a - jr z, directs ; exact blocks - inc d ; load the partial - ; - ; Now it's load time - ; -directs: - push de - ld a,d ; number of blocks - cp #18 - jr z, shortfile - ld a,#18 ; direct blocks -shortfile: - ld b,a - ld hl,#loadbuf - ld ix,#ibuf + I_ADDR - call breadset ; read b blocks from the list in ix - pop de - ret nz - ; See what indirects are needed if any - ld a,d - cp #19 - jr c, load_done - push de - push hl - ld e,(ix) - inc ix - ld d,(ix) - inc ix - ld hl,#dbuf - call bread ; load the indirect block - pop de - pop hl - ld a,d - sub #18 ; direct blocks - ld b,a ; remainder - ld ix,#dbuf - call breadset - ret nz -load_done: - ; File now loaded - xor a - ret -retnz: - or a - ret - -; -; Load inode HL into ibuf -; -; Entry: HL = inode number, A = type bits -; -; Return: NZ = error, Z = ok, data in ibuf -; -; Destroys: AF/BC/DE/HL -; -iget: - ; Turn an inode into a block - push af - push hl - ex de,hl - srl d ; Divide inode by 8 (64 bytes per inode) - srl e - srl d - srl e - srl d - srl e - ld hl,#dbuf - call bread - pop hl - jr nz, badiget - ld a,l - and #0x07 ; inode offset in block - add a,a ; x2 - add a,a ; x4 - add a,a ; x8 - add a,a ; x16 - add a,a ; x32 - ld h,#0 - ld l,a - add hl,hl ; x64 - ld de,#dbuf - add hl,de ; valid pointer - ex de,hl - ld hl,#I_TYPE+1 - add hl,de ; hl is now the type bits - ld a,(hl) - and #0xF0 ; type bits - ld l,a - pop af - cp l - ret nz ; wrong type of file - ex de,hl ; get pointer back into hl - ld de,#ibuf - ld bc,#64 - ldir - ret ; Z -badiget: - pop af - ret - -; -; Read a set of blocks listed in the array at ix. Any zero entry means -; a sparse block (zero the memory). -; -; Entry: IX = table, B = count, HL = load address -; -; Return: Z = success, HL = next load address -; -; Destroys: AF BC DE IX -; -; -breadset: -reader_loop: - ld e,(ix) - inc ix - ld d,(ix) - inc ix - push bc - call bread ; read block DE to HL and move HL on - pop bc - ret nz - djnz reader_loop - ret - -; -; bread -; -; Load a disk block (512 bytes) or zero block -; -; HL = buffer to read into -; DE = block relative to partbase -; -; return -; NZ = fail, Z = ok -; HL = next read address -; BC, DE, AF destroyed -; IX, IY preserved -; -bread: - ld a,d - or e - jr nz, bread_disk - ld d,h - ld e,l - ld bc,#511 - ld (hl),#0 - inc de - ldir - inc hl - ret - -; -; Compare the name at IX with the one in HL -; -; Returns Z = matched -; -; Destroys BC,HL,IX -; -; -cmpname: ; check name in IX matches HL for 30 chars - ld b,#30 -cmploop: - ld a,(ix) - cp (hl) - ret nz - or a - ret z ; First matched \0 matches all - inc hl - inc ix - djnz cmploop - ret ; Z - - + .include '../filo/filo.s' ; ; **************************************************************************** ; @@ -493,6 +133,22 @@ ide_wait_drq: xor a ret +; +; Drive Set +; +; A = drive 0-15 +; +; For now just drive A +; +drive_set: + or a + ret z + ld hl,#bad_drive + jr con_write + +bad_drive: + .asciz 'Invalid drive.\n' +; ; ; Console I/O ; -- 2.34.1