From a7d4459a01768d5453a446300c598bdd81729cd7 Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Sun, 24 Apr 2016 21:51:37 -0700 Subject: [PATCH] Preserve Partition Table in SYSCOPY Updated FLASH to latest version --- Doc/Flash4.txt | 368 ++++++++++++++------------- Source/Apps/Assign.asm | 2 +- Source/Apps/Format.asm | 206 ++++++++++++++- Source/Apps/SysCopy.asm | 55 +++- Source/HBIOS/prefix.asm | 135 +++++++--- Source/RomDsk/ROM_1024KB/FDISK80.COM | Bin 20480 -> 20480 bytes Source/RomDsk/ROM_1024KB/FLASH.COM | Bin 12321 -> 12419 bytes Source/RomDsk/ROM_512KB/FDISK80.COM | Bin 20480 -> 20480 bytes Source/RomDsk/ROM_512KB/FLASH.COM | Bin 12321 -> 12419 bytes 9 files changed, 529 insertions(+), 237 deletions(-) diff --git a/Doc/Flash4.txt b/Doc/Flash4.txt index c0308a34..327f8c84 100644 --- a/Doc/Flash4.txt +++ b/Doc/Flash4.txt @@ -1,182 +1,186 @@ - - FLASH4 (c) 2014 William R Sowerbutts - http://sowerbutts.com/8bit/ - -= Warning = - -FLASH4 has been tested and confirmed working on: - * N8VEM SBCv2 - * N8VEM N8-2312 - * N8VEM Mark IV SBC - * DX-Designs P112 - * ZETA SBC v2 - -However it remains somewhat experimental. If it works for you, please let me -know. If it breaks please also let me know so I can fix it! - - -= Introduction = - -FLASH4 is a CP/M program which can read, write and verify Flash ROM contents to -or from an image file stored on a CP/M filesystem. It is intended for in-system -programming of Flash ROM chips on Z80 and Z180 systems. - -FLASH4 aims to support a range of Flash ROM chips. Ideally I would like to -support all Flash ROM chips that are in use in Z80/Z180 N8VEM machines. If -FLASH4 does not support your chip please let me know and I will try to add -support. - -When writing to the Flash ROM chip, FLASH4 will only reprogram the sectors -whose contents have changed. This helps to reduce wear on the flash memory, -makes the reprogram operation faster, and reduces the risk of leaving the -system unbootable if power fails during a reprogramming operation. FLASH4 -always performs a full verify operation after writing to the chip to confirm -that the correct data has been loaded. - -FLASH4 is reasonably fast. Reprogramming and verifying every sector on a 512KB -SST 39F040 chip takes 21 seconds on my Mark IV SBC, versus 45 seconds to -perform the same task using a USB MiniPro TL866 EEPROM programmer under Linux -on my PC. If only a subset of sectors require reprogramming FLASH4 will be -even faster. - -FLASH4 works with binary ROM image files, it does not support Intel Hex format -files. Hex files can be easily converted to or from binaries using "hex2bin" or -the "srec_cat" program from SRecord: - - $ srec_cat image.hex -intel -fill 0xFF 0 0x80000 -output image.bin -binary - $ srec_cat image.bin -binary -output image.hex -intel - -FLASH4 can use several different methods to access the Flash ROM chip. The best -available method is determined automatically at run time. Alternatively you may -provide a command-line option to force the use of a specific method. - -The first two methods use bank switching to map sections of the ROM into the -CPU address space. FLASH4 will detect the presence of RomWBW or UNA BIOS and -use the bank switching methods they provide. - -On P112 systems the P112 B/P BIOS is detected and P112 bank switching is used. - -If no bank switching method can be auto-detected, and the system has a Z180 -CPU, FLASH4 will use the Z180 DMA engine to access the Flash ROM chip. This -does not require any bank switching but it is slower and will not work on all -platforms. - -Z180 DMA access requires the flash ROM to be linearly mapped into the lower -region of physical memory, as it is on the Mark IV SBC (for example). The -N8-2312 has additional memory mapping hardware, consequently Z180 DMA access on -the N8-2312 is NOT SUPPORTED and if forced will corrupt the contents of RAM; -use one of the supported bank switching methods instead. - -Z180 DMA access requires the Z180 CPU I/O base control register configured to -locate the internal I/O addresses at 0x40 (ie ICR bits IOA7, IOA6 = 0, 1). - - -= Usage = - -The three basic operations are: - - FLASH4 WRITE filename [options] - -This will rewrite the flash ROM contents from the named file. The file size -must exactly match the size of the ROM chip. After the write operation, a -verify operation will be performed automatically. - - FLASH4 VERIFY filename [options] - -This will read out the flash ROM contents and report if it matches the contents -of the named file. The file size must exactly match the size of the ROM chip. - - FLASH4 READ filename [options] - -This will read out the entire flash ROM contents and write it to the named -file. - -If your ROM chip is larger than the image you wish to write, use the "/PARTIAL" -(or "/P") command line option. To avoid accidentally flashing the wrong file, -the image file must be an exact multiple of 32KB in length. The portion of the -ROM not occupied by the image file is left either unmodified or erased. - -If you are using an ROM/EPROM/EEPROM chip which cannot be programmed in-system, -FLASH4 will not be able to recognise it, however the software can still -usefully READ and VERIFY the chip. Use the "/ROM" command line option to enable -"READ" or "VERIFY" mode with unrecognised chips. This mode assumes a 512K ROM -is fitted; smaller ROMs will be treated as a 512K ROM with the data repated -multiple times -- with a 256K chip the data is repeated twice, four times for a -128K chip, etc. - -One of the following optional command line arguments may be specified at the -end of the command line to force FLASH4 to use a particular method to access -the flash ROM chip: - - /ROMWBW For ROMWBW BIOS version 2.6 and later - /ROMWBWOLD For ROMWBW BIOS version 2.5 and earlier - /UNABIOS For UNA BIOS - /Z180DMA For Z180 DMA - /P112 For DX-Designs P112 - -If no option is specified FLASH4 attempts to determine the best available -method automatically. - - -= Supported chips and features = - -FLASH4 will interrogate your flash ROM chip to identify it automatically. -FLASH4 assumes that you have a single flash ROM device and it is located at the -bottom of the physical memory map. - -FLASH4 does not support setting or resetting the protection bits on individual -sectors within Flash ROM devices. If your Flash ROM chip has protected sectors -you will need to unprotect them by other means before FLASH4 can erase and -reprogram them. - -AT29C series chips employ an optional "software data protection" feature. This -is supported by FLASH4 and is left activated after programming the chip to -prevent accidental reprogramming of sectors. - -The following chips are supported: - - AT29F010 - AT29F040 - M29F010 - M29F040 - MX29F040 - SST 39F010 - SST 39F020 - SST 39F040 - AT29C512 - AT29C040 - AT29C010 - AT29C020 - -The following chips are supported but have unequal sector sizes; FLASH4 will -only erase and reprogram the entire chip at once rather than its normal -sector-by-sector operation: - - AT49F001NT - AT49F001N - AT49F002N - AT49F002NT - AT49F040 - -If you use a flash ROM chip that is not listed above please email me -(will@sowerbutts.com) and I will try to add support for it. - - -= Compiling = - -The software is written in a mix of C and assembler. It builds using the SDCC -toolchain and the SRecord tools. A Makefile is provided to build the executable -in Linux and I imagine it can be easily modified to build in Windows. - -You may need to adjust the path to the SDCC libraries in the Makefile if your -sdcc installation is not in /usr/local - - -= License = - -FLASH4 is licensed under the The GNU General Public License version 3 (see -included "LICENSE.txt" file). - -FLASH4 is provided with NO WARRANTY. In no event will the author be liable for -any damages. Use of this program is at your own risk. May cause rifts in space -and time. + + FLASH4 (c) 2014 William R Sowerbutts + http://sowerbutts.com/8bit/ + += Warning = + +FLASH4 has been tested and confirmed working on: + * N8VEM SBCv2 + * N8VEM N8-2312 + * N8VEM Mark IV SBC + * DX-Designs P112 + * ZETA SBC v2 + +However it remains somewhat experimental. If it works for you, please let me +know. If it breaks please also let me know so I can fix it! + + += Introduction = + +FLASH4 is a CP/M program which can read, write and verify Flash ROM contents to +or from an image file stored on a CP/M filesystem. It is intended for in-system +programming of Flash ROM chips on Z80 and Z180 systems. + +FLASH4 aims to support a range of Flash ROM chips. Ideally I would like to +support all Flash ROM chips that are in use in Z80/Z180 N8VEM machines. If +FLASH4 does not support your chip please let me know and I will try to add +support. + +When writing to the Flash ROM chip, FLASH4 will only reprogram the sectors +whose contents have changed. This helps to reduce wear on the flash memory, +makes the reprogram operation faster, and reduces the risk of leaving the +system unbootable if power fails during a reprogramming operation. FLASH4 +always performs a full verify operation after writing to the chip to confirm +that the correct data has been loaded. + +FLASH4 is reasonably fast. Reprogramming and verifying every sector on a 512KB +SST 39F040 chip takes 21 seconds on my Mark IV SBC, versus 45 seconds to +perform the same task using a USB MiniPro TL866 EEPROM programmer under Linux +on my PC. If only a subset of sectors require reprogramming FLASH4 will be +even faster. + +FLASH4 works with binary ROM image files, it does not support Intel Hex format +files. Hex files can be easily converted to or from binaries using "hex2bin" or +the "srec_cat" program from SRecord: + + $ srec_cat image.hex -intel -fill 0xFF 0 0x80000 -output image.bin -binary + $ srec_cat image.bin -binary -output image.hex -intel + +FLASH4 can use several different methods to access the Flash ROM chip. The best +available method is determined automatically at run time. Alternatively you may +provide a command-line option to force the use of a specific method. + +The first two methods use bank switching to map sections of the ROM into the +CPU address space. FLASH4 will detect the presence of RomWBW or UNA BIOS and +use the bank switching methods they provide. + +On P112 systems the P112 B/P BIOS is detected and P112 bank switching is used. + +If no bank switching method can be auto-detected, and the system has a Z180 +CPU, FLASH4 will use the Z180 DMA engine to access the Flash ROM chip. This +does not require any bank switching but it is slower and will not work on all +platforms. + +Z180 DMA access requires the flash ROM to be linearly mapped into the lower +region of physical memory, as it is on the Mark IV SBC (for example). The +N8-2312 has additional memory mapping hardware, consequently Z180 DMA access on +the N8-2312 is NOT SUPPORTED and if forced will corrupt the contents of RAM; +use one of the supported bank switching methods instead. + +Z180 DMA access requires the Z180 CPU I/O base control register configured to +locate the internal I/O addresses at 0x40 (ie ICR bits IOA7, IOA6 = 0, 1). + + += Usage = + +The three basic operations are: + + FLASH4 WRITE filename [options] + +This will rewrite the flash ROM contents from the named file. The file size +must exactly match the size of the ROM chip. After the write operation, a +verify operation will be performed automatically. + + FLASH4 VERIFY filename [options] + +This will read out the flash ROM contents and report if it matches the contents +of the named file. The file size must exactly match the size of the ROM chip. + + FLASH4 READ filename [options] + +This will read out the entire flash ROM contents and write it to the named +file. + +If your ROM chip is larger than the image you wish to write, use the "/PARTIAL" +(or "/P") command line option. To avoid accidentally flashing the wrong file, +the image file must be an exact multiple of 32KB in length. The portion of the +ROM not occupied by the image file is left either unmodified or erased. + +If you are using an ROM/EPROM/EEPROM chip which cannot be programmed in-system, +FLASH4 will not be able to recognise it, however the software can still +usefully READ and VERIFY the chip. Use the "/ROM" command line option to enable +"READ" or "VERIFY" mode with unrecognised chips. This mode assumes a 512K ROM +is fitted; smaller ROMs will be treated as a 512K ROM with the data repated +multiple times -- with a 256K chip the data is repeated twice, four times for a +128K chip, etc. + +One of the following optional command line arguments may be specified at the +end of the command line to force FLASH4 to use a particular method to access +the flash ROM chip: + +BIOS interfaces: + /ROMWBW For ROMWBW BIOS version 2.6 and later + /ROMWBWOLD For ROMWBW BIOS version 2.5 and earlier + /UNABIOS For UNA BIOS + +Direct hardware interfaces: + /Z180DMA For Z180 DMA + /P112 For DX-Designs P112 + /N8VEMSBC For N8VEM SBC (v1, v2), Zeta (v1) SBC + +If no option is specified FLASH4 attempts to determine the best available +method automatically. + + += Supported chips and features = + +FLASH4 will interrogate your flash ROM chip to identify it automatically. +FLASH4 assumes that you have a single flash ROM device and it is located at the +bottom of the physical memory map. + +FLASH4 does not support setting or resetting the protection bits on individual +sectors within Flash ROM devices. If your Flash ROM chip has protected sectors +you will need to unprotect them by other means before FLASH4 can erase and +reprogram them. + +AT29C series chips employ an optional "software data protection" feature. This +is supported by FLASH4 and is left activated after programming the chip to +prevent accidental reprogramming of sectors. + +The following chips are supported: + + AT29F010 + AT29F040 + M29F010 + M29F040 + MX29F040 + SST 39F010 + SST 39F020 + SST 39F040 + AT29C512 + AT29C040 + AT29C010 + AT29C020 + +The following chips are supported but have unequal sector sizes; FLASH4 will +only erase and reprogram the entire chip at once rather than its normal +sector-by-sector operation: + + AT49F001NT + AT49F001N + AT49F002N + AT49F002NT + AT49F040 + +If you use a flash ROM chip that is not listed above please email me +(will@sowerbutts.com) and I will try to add support for it. + + += Compiling = + +The software is written in a mix of C and assembler. It builds using the SDCC +toolchain and the SRecord tools. A Makefile is provided to build the executable +in Linux and I imagine it can be easily modified to build in Windows. + +You may need to adjust the path to the SDCC libraries in the Makefile if your +sdcc installation is not in /usr/local + + += License = + +FLASH4 is licensed under the The GNU General Public License version 3 (see +included "LICENSE.txt" file). + +FLASH4 is provided with NO WARRANTY. In no event will the author be liable for +any damages. Use of this program is at your own risk. May cause rifts in space +and time. diff --git a/Source/Apps/Assign.asm b/Source/Apps/Assign.asm index 9dde56ac..dae8fc47 100644 --- a/Source/Apps/Assign.asm +++ b/Source/Apps/Assign.asm @@ -1729,4 +1729,4 @@ msgnoa .db "Drive A: is unassigned, aborting!",0 msgdos .db "DOS error, return code=0x",0 msgmem .db " Disk Buffer Bytes Free",0 ; - .end \ No newline at end of file + .end diff --git a/Source/Apps/Format.asm b/Source/Apps/Format.asm index 79cc4eeb..96f9bdb5 100644 --- a/Source/Apps/Format.asm +++ b/Source/Apps/Format.asm @@ -5,24 +5,210 @@ ; AUTHOR: WAYNE WARTHEN (wwarthen@gmail.com) ;_______________________________________________________________________________ ; -; CHANGELOG: +; Usage: +; FORMAT D: +; ex: FORMAT (display version and usage) +; FORMAT /? (display version and usage) +; FORMAT C: (format drive C:) ;_______________________________________________________________________________ ; -; TODO: +; Change Log: +;_______________________________________________________________________________ ; +; ToDo: +; 1) Actually implement this ;_______________________________________________________________________________ ; +;=============================================================================== +; Definitions +;=============================================================================== +; +stksiz .equ $40 ; Working stack size +; +restart .equ $0000 ; CP/M restart vector +bdos .equ $0005 ; BDOS invocation vector +;; +;stamp .equ $40 ; loc of RomWBW CBIOS zero page stamp +; +rmj .equ 2 ; CBIOS version - major +rmn .equ 8 ; CBIOS version - minor +; +;=============================================================================== +; Code Section +;=============================================================================== +; +; + .org $100 +; + ; setup stack (save old value) + ld (stksav),sp ; save stack + ld sp,stack ; set new stack +; + ; initialization + call init ; initialize + jr nz,exit ; abort if init fails +; + ; do the real work + call process ; parse and process command line + jr nz,exit ; done if error or no action +; +exit: ; clean up and return to command processor + call crlf ; formatting + ld sp,(stksav) ; restore stack + jp restart ; return to CP/M via restart + ret ; return to CP/M w/o restart +; +; Initialization +; +init: +; + ; locate start of cbios (function jump table) + ld hl,(restart+1) ; load address of CP/M restart vector + ld de,-3 ; adjustment for start of table + add hl,de ; HL now has start of table + ld (bioloc),hl ; save it +; + ; check for UNA (UBIOS) + ld a,($FFFD) ; fixed location of UNA API vector + cp $C3 ; jp instruction? + jr nz,initx ; if not, not UNA + ld hl,($FFFE) ; get jp address + ld a,(hl) ; get byte at target address + cp $FD ; first byte of UNA push ix instruction + jr nz,initx ; if not, not UNA + inc hl ; point to next byte + ld a,(hl) ; get next byte + cp $E5 ; second byte of UNA push ix instruction + jr nz,initx ; if not, not UNA + ld hl,unamod ; point to UNA mode flag + ld (hl),$FF ; set UNA mode flag +; +initx: +; + xor a + ret +; +; Process command line +; +process: + jr usage +; + xor a + ret +; +usage: +; + call crlf ; formatting + ld de,msgban1 ; point to version message part 1 + call prtstr ; print it + ld a,(unamod) ; get UNA flag + or a ; set flags + ld de,msghb ; point to HBIOS mode message + call z,prtstr ; if not UNA, say so + ld de,msgub ; point to UBIOS mode message + call nz,prtstr ; if UNA, say so + call crlf ; formatting + ld de,msgban2 ; point to version message part 2 + call prtstr ; print it + call crlf2 ; blank line + ld de,msguse ; point to usage message + call prtstr ; print it + xor a ; signal success + ret ; and return +; +; Print character in A without destroying any registers +; +prtchr: + push bc ; save registers + push de + push hl + ld e,a ; character to print in E + ld c,$02 ; BDOS function to output a character + call bdos ; do it + pop hl ; restore registers + pop de + pop bc + ret +; +; Print a zero terminated string at (HL) without destroying any registers +; +prtstr: + push de +; +prtstr1: + ld a,(de) ; get next char + or a + jr z,prtstr2 + call prtchr + inc de + jr prtstr1 +; +prtstr2: + pop de ; restore registers + ret +; +; Start a new line +; +crlf2: + call crlf ; two of them +crlf: + push af ; preserve AF + ld a,13 ; + call prtchr ; print it + ld a,10 ; + call prtchr ; print it + pop af ; restore AF + ret +; +; Invoke CBIOS function +; The CBIOS function offset must be stored in the byte +; following the call instruction. ex: +; call cbios +; .db $0C ; offset of CONOUT CBIOS function +; +cbios: + ex (sp),hl + ld a,(hl) ; get the function offset + inc hl ; point past value following call instruction + ex (sp),hl ; put address back at top of stack and recover HL + ld hl,(bioloc) ; address of CBIOS function table to HL + call addhl ; determine specific function address + jp (hl) ; invoke CBIOS +; +; Add the value in A to HL (HL := HL + A) +; +addhl: + add a,l ; A := A + L + ld l,a ; Put result back in L + ret nc ; if no carry, we are done + inc h ; if carry, increment H + ret ; and return +; +; Jump indirect to address in HL +; +jphl: + jp (hl) ; ;=============================================================================== -; MAIN PROGRAM PROCEDURE +; Storage Section ;=============================================================================== ; - .ORG 00100H - RET +bioloc .dw 0 ; CBIOS starting address +; +unamod .db 0 ; $FF indicates UNA UBIOS active +; +stksav .dw 0 ; stack pointer saved at start + .fill stksiz,0 ; stack +stack .equ $ ; stack top ; -STACKSAV .DW 0 -STACKSIZ .EQU 40H ; WE ARE A STACK PIG - .FILL STACKSIZ,0 -STACK .EQU $ +msgban1 .db "FORMAT v0.1 for RomWBW CP/M 2.2, 24-Apr-2016",0 +msghb .db " (HBIOS Mode)",0 +msgub .db " (UBIOS Mode)",0 +msgban2 .db "Copyright 2016, Wayne Warthen, GNU GPL v3",0 +msguse .db "FORMAT command is not yet implemented!",13,10,13,10 + .db "Use FD command to physically format floppy diskettes",13,10 + .db "Use CLRDIR command to (re)initialize directories",13,10 + .db "Use SYSCOPY command to make disks bootable",13,10 + .db "Use FDISK80 command to partition mass storage media",0 ; - .END + .end diff --git a/Source/Apps/SysCopy.asm b/Source/Apps/SysCopy.asm index 17e50f67..ffb146bf 100644 --- a/Source/Apps/SysCopy.asm +++ b/Source/Apps/SysCopy.asm @@ -15,6 +15,7 @@ ;_______________________________________________________________________________ ; ; Change Log: +; 2016-04-24 [WBW] Updated to preserve MBR partition table ;_______________________________________________________________________________ ; ; ToDo: @@ -31,7 +32,8 @@ stksiz .equ $40 ; we are a stack pig restart .equ $0000 ; CP/M restart vector bdos .equ $0005 ; BDOS invocation vector ; -buf .equ $900 ; load point for system image (from original SYSGEN) +imgbuf .equ $900 ; load point for system image (from original SYSGEN) +mbrbuf .equ imgbuf+$4000 ; load point for MBR storage ; ;=============================================================================== ; Code Section @@ -142,16 +144,16 @@ confirm: ld de,sconf3 call prtstr ; - ; get input + ; get input (imgbuf is used for temp storage) ld c,$0A ; get console buffer - ld de,buf ; into buf + ld de,imgbuf ; into buf ld a,1 ; max of 1 character ld (de),a ; set up buffer call bdos ; invoke BDOS - ld a,(buf+1) ; get num chars entered + ld a,(imgbuf+1) ; get num chars entered dec a ; check that we got exactly one char jr nz,confirm ; bad input, re-prompt - ld a,(buf+2) ; get the character + ld a,(imgbuf+2) ; get the character and $DF ; force upper case cp 'Y' ; compare to Y ret ; return with Z set appropriately @@ -190,7 +192,7 @@ rdfil: ld (rwfun),a ; save bdos function ld a,12 ; start with 1536 byte header (12 records) ld (reccnt),a ; init record counter - ld hl,buf ; start of buffer + ld hl,imgbuf ; start of buffer ld (bufptr),hl ; init buffer pointer call rwfil ; read the header ret nz ; abort on error (no need to close file) @@ -237,7 +239,7 @@ wrfil1: ; create target file ld (rwfun),a ; save bdos function ld a,(imgsiz) ; number of records to read ld (reccnt),a ; init record counter - ld hl,buf ; start of buffer + ld hl,imgbuf ; start of buffer ld (bufptr),hl ; init buffer pointer call rwfil ; do it ret nz ; abort on error @@ -329,7 +331,36 @@ wrdsk: ; force return to go through disk reset ld hl,resdsk ; load address of reset disk routine push hl ; and put it on the stack - ; set drive for subsequent writes + ; setup to read existing MBR + ld a,(destfcb) ; get the drive + dec a ; adjust for zero indexing + call setdsk ; setup disk + ret nz ; abort on error + ld hl,mbrbuf ; override to read + ld (bufptr),hl ; ... into MBR buffer + ld a,4 ; 4 records = 1 512 byte sector + ; set function to read + ld hl,(cbftbl) ; get address of CBIOS function table + ld a,$27 ; $27 is CBIOS READ entry offset + call addhl ; set HL to resultant entry point + ld (actfnc),hl ; save it + ; read the existing MBR into memory + call rwdsk ; read the sector + ret nz ; abort on error + ; test for valid partition table ($55, $AA at offset $1FE) + ld hl,(mbrbuf+$1FE); HL := signature + ld a,$55 ; load expected value of first byte + cp l ; check for proper value + jr nz,wrdsk1 ; mismatch, ignore old partition table + ld a,$AA ; load expected value of second byte + cp h ; check for proper value + jr nz,wrdsk1 ; mismatch, ignore old partition table + ; valid MBR, copy existing partition table over to new image + ld hl,mbrbuf+$1BE ; copy from MBR offset of existing MBR + ld de,imgbuf+$1BE ; copy to MBR offset of new image + ld bc,$40 ; size of MBR + ldir ; do it +wrdsk1: ; setup to write the image from memory to disk ld a,(destfcb) ; get the drive dec a ; adjust for zero indexing call setdsk ; setup disk @@ -396,7 +427,7 @@ setdsk: ld hl,0 ld (acttrk),hl ; active track := 0 ld (actsec),hl ; active sector := 0 - ld hl,buf + ld hl,imgbuf ; assume r/w to image buffer ld (bufptr),hl ; reset buffer pointer ; xor a ; signal success @@ -458,14 +489,14 @@ jphl: jp (hl) ; indirect jump ; chkhdr: ; check signature - ld hl,(buf+$580) ; get signature + ld hl,(imgbuf+$580) ; get signature ld de,$A55A ; signature value or a ; clear CF sbc hl,de ; compare jp nz,errsig ; invalid signature ; compute the image size (does not include size of header) - ld hl,(buf+$5FC) ; get CPM_END - ld de,(buf+$5FA) ; get CPM_LOC + ld hl,(imgbuf+$5FC) ; get CPM_END + ld de,(imgbuf+$5FA) ; get CPM_LOC or a ; clear CF sbc hl,de ; image size := CPM_END - CPM_LOC xor a ; signal success diff --git a/Source/HBIOS/prefix.asm b/Source/HBIOS/prefix.asm index 52ef04cc..0916b3ef 100644 --- a/Source/HBIOS/prefix.asm +++ b/Source/HBIOS/prefix.asm @@ -1,20 +1,52 @@ -;---------------------------------------------------------------------------- -; PREFIX_UNA.ASM +;=============================================================================== +; PREFIX.ASM ; -; PUT AT THE HEAD OF BOOT.BIN TO XFER TO A FLOPPY DISK +; CP/M DISK FORMATS ALLOW FOR RESERVED TRACKS THAT CONTAIN AN IMAGE OF THE +; OPERATING SYSTEM TO BE LOADED WHEN THE DISK IS BOOTED. THE OPERATING SYSTEM +; IMAGE ITSELF IS NORMALLY PREFIXED BY A 1-N SECTORS CONTAINING OS BOOTSTRAP +; CODE AND DISK METADATA. +; +; THE RETROBREW COMPUTING GROUP HAS BEEN USING A CONVENTION OF PREFIXING THE +; OS IMAGE WITH 3 SECTORS (512 BYTES X 3 FOR A TOTAL OF 1536 BYTES): +; +; SECTOR 1: IBM-PC STYLE BOOT BLOCK CONTAINING BOOTSTRAP, +; PARTITION TABLE, AND BOOT SIGNATURE +; SECTOR 2: RESERVED +; SECTOR 3: METADATA +; +; THE HARDWARE BIOS IS EXPECTED TO READ AND LOAD THE FIRST TWO SECTORS FROM THE +; DISK TO MEMORY ADDRESS $8000 AND JUMP TO THAT LOCATION TO BEGIN THE BOOT +; PROCESS. THE BIOS IS EXPECTED TO VERIFY THAT A STANDARD BOOT SIGNATURE +; OF $55, $AA IS PRESENT AT OFFSET $1FE-$1FF. IF THE SIGNATURE IS NOT FOUND, +; THE BIOS SHOULD ASSUME THE DISK HAS NOT BEEN PROPERLY INITIALIZED AND SHOULD +; NOT JUMP TO THE LOAD ADDRESS. +; +;=============================================================================== ; -;---------------------------------------------------------------------------- - #INCLUDE "std.asm" - BYT .EQU 1 ; used to describe METADATA_SIZE below WRD .EQU 2 - +; SECTOR_SIZE .EQU 512 BLOCK_SIZE .EQU 128 PREFIX_SIZE .EQU (3 * SECTOR_SIZE) ; 3 SECTORS METADATA_SIZE .EQU BYT+WRD+(4*BYT)+16+BYT+WRD+WRD+WRD+WRD ; (as defined below) - +; +PARTTBL_LOC .EQU $1BE +PARTTBL_SIZ .EQU $40 +BOOTSIG_LOC .EQU $1FE +; +;------------------------------------------------------------------------------- +; SECTOR 1 +; +; THIS SECTOR FOLLOWS THE CONVENTIONS OF AN IBM-PC MBR CONTAINING THE OS +; BOOTSTRAP CODE, PARTITION TABLE, AND BOOT SIGNATURE +; +;---------------------------------------------------------------------------- +; +; THE FOLLOWING BOOTSTRAP CODE IS BUILT TO ASSUME IT WILL BE EXECUTED AT A STARTING +; ADDRESS OF $8000. +; .ORG $8000 JR BOOT ; @@ -114,37 +146,76 @@ HEXCONV: RET ; ERROR: - LD DE,STR_ERR ; POINT TO ERROR STRING - CALL PRTSTR ; PRINT IT - HALT ; HALT + LD DE,STR_ERR ; POINT TO ERROR STRING + CALL PRTSTR ; PRINT IT + HALT ; HALT +; +; DATA ; STR_LOAD .DB "\r\nLoading",0 STR_DONE .DB "\r\n",0 STR_ERR .DB " Read Error!",0 ; - .ORG $ - $8000 + .ORG $ - $8000 ; RESTORE ORG + .FILL PARTTBL_LOC - $ ; FILL TO START OF PARTITION TABLE +; +; RESERVE SPACE FOR STANDARD IBM-PC PARTITION TABLE. ALTHOUGH A +; PARTITION TABLE IS NOT RELEVANT FOR A FLOPPY DISK, IT DOES NO HARM. +; THE CONTENTS OF THE PARTITION TABLE MUST BE MANAGED BY FDISK80. +; +PARTTBL .FILL PARTTBL_SIZ,$00 ; PARTITION TABLE, FILL WITH ZEROES +; +; THE END OF THE FIRST SECTOR MUST CONTAIN THE TWO BYTE BOOT +; SIGNATURE. ; - .FILL (SECTOR_SIZE) - $ - 2 - .DW $AA55 +BOOTSIG .DB $55,$AA ; STANDARD BOOT SIGNATURE ; - .FILL ((PREFIX_SIZE - BLOCK_SIZE) - $),00H -PR_SIG .DW $A55A ; SIGNATURE GOES HERE +;------------------------------------------------------------------------------- +; SECTOR 2 ; -PR_PLATFORM .DB PLATFORM -PR_DEVICE .DB 0 -PR_FORMATTER .DB 0,0,0,0,0,0,0,0 -PR_DRIVE .DB 0 -PR_LOG_UNIT .DW 0 - +; THIS SECTOR HAS NOT BEEN DEFINED AND IS RESERVED. +; +;---------------------------------------------------------------------------- +; + .FILL 512,0 ; JUST FILL SECTOR WITH ZEROES +; +;------------------------------------------------------------------------------- +; SECTOR 3 +; +; OS AND DISK METADATA +; +;---------------------------------------------------------------------------- +; + .FILL 128 * 3,0 ; FIRST 384 BYTES ARE NOT YET DEFINED +; +; THE FOLLOWING TWO BYTES ARE AN ADDITIONAL SIGNATURE THAT IS VERIFIED BY +; SOME HARDWARE BIOSES. +; +PR_SIG .DB $5A,$A5 ; SIGNATURE GOES HERE +; +; FIRST CHUNK OF METADATA IMMEDIATELY FOLLOWS THE SIGNATURE BYTES +; +PR_PLATFORM .DB PLATFORM ; PLATFORM ID (SEE STD.ASM) +PR_DEVICE .DB 0 ; ? (PROBABLY UNUSED) +PR_FORMATTER .DB 0,0,0,0,0,0,0,0 ; ? (PROBABLY UNUSED) +PR_DRIVE .DB 0 ; ? (PROBABLY UNUSED) +PR_LOG_UNIT .DW 0 ; ? (PROBABLY UNUSED) +; +; FILLER TO PLACE SECOND CHUNK OF METADATA AT THE END OF THE SECTOR ; .FILL ((PREFIX_SIZE - METADATA_SIZE) - $),00H - .DB 0 ; write protect boolean - .DW 0 ; starting update number - .DB RMJ,RMN,RUP,RTP - .DB "Unlabeled Drive ","$" - .DW 0 ; PTR TO LOCATION TO STORE DISKBOOT & BOOTDRIVE (SEE CNFGDATA) - .DW CPM_LOC ; CCP START - .DW CPM_END ; END OF CBIOS - .DW CPM_ENT ; COLD BOOT LOCATION - - .END \ No newline at end of file +; +; SECOND CHUNK OF METADATA +; +PR_WP .DB 0 ; WRITE PROTECT BOOLEADN +PR_UPDSEQ .DW 0 ; PREFIX UPDATE SEQUENCE NUMBER (DEPRECATED?) +PR_VER .DB RMJ,RMN,RUP,RTP ; OS BUILD VERSION +PR_LABEL .DB "Unlabeled Drive ","$" ; DISK LABEL (EXACTLY 16 BYTES!!!) + .DW 0 ; DEPRECATED +PR_LDLOC .DW CPM_LOC ; ADDRESS TO START LOADING OS +PR_LDEND .DW CPM_END ; ADDRESS TO STOP LOADING OS +PR_ENTRY .DW CPM_ENT ; ADDRESS TO ENTER OS +; +; +; + .END diff --git a/Source/RomDsk/ROM_1024KB/FDISK80.COM b/Source/RomDsk/ROM_1024KB/FDISK80.COM index dfe3f66846114e7734bcd77447edc69785a7c5c9..4523c291d00e4d0cf7b113b340d673dcf3ad2e79 100644 GIT binary patch delta 16 YcmZozz}T>Walt!ke06HWFs{jB1 delta 16 YcmZozz}T>Walt!ke06IbjumAu6 diff --git a/Source/RomDsk/ROM_1024KB/FLASH.COM b/Source/RomDsk/ROM_1024KB/FLASH.COM index c62108d5ff8cafa23ae8d1c85a097c639616ac97..1b7fa64ce2c860b5da85cce18f983c4a0fb65c20 100644 GIT binary patch delta 4902 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 delta 16 YcmZozz}T>Walt!ke06IbjumAu6 diff --git a/Source/RomDsk/ROM_512KB/FLASH.COM b/Source/RomDsk/ROM_512KB/FLASH.COM index c62108d5ff8cafa23ae8d1c85a097c639616ac97..1b7fa64ce2c860b5da85cce18f983c4a0fb65c20 100644 GIT binary patch delta 4902 zcmcf_YgAO__B-=p@ClK697WD2O2eq=WoXP2x>lmM3~!lK+#5Z}F)Oh|?vz*0j8d8v zXq+ovC9v$FNp{9cs2|mmS=3@?9oO;!cU5<1rU#!uqoTYA%E$L*AG@x;fKOl$QAhWX+-4hdN*w|1JR)&IMay~-Aut|356-ms60 zS>snDs#3l8-UZy`zxeCy37K|VrhP)DeR!swYg~PJ)!`Q!S1XoY94_=Vay{HxdSH#} z@JInJZ4{euW2QYR)1I1Xzai6ZqJ%V3pTrq%G*4d3q-=&%>&)8tepuG7+kL2^V>_sB@n zq|vx2O)9gD_4cb~6DFHgkk@L}-nSwX1;@9Ni;7M?aFE z4`;<_ln_bLAvaQo1_q^%Vn)sSrLOmc@dL~Ipy&#$h(K{~{7xBtoq_$)>gR28`c650 zmz@5AoW5I@(`)4P59Rbda{5P-#hS|Pl%`on*k^74@p7H;5Qv>EM&UkmYNyO{&VZZK zK&}CSwA4Cf%G?cVQ-c=5FfG~7`LGM2unXMX2rh%WQ*|uSy9HxhB7I|>ZhmkBhDS2S z-ek>sg)Y&4q{rT2YgxN`)b_>k!(UaKGy%c^kM+2;fr5>Xsz?(D?GQsCs2c z35X}a(*dFio=aI)-U^|P6bM}!nJIK&Vx%_)3Eq}WRskpL?1Sl^GA*lYp6e6=*J=E= z;kTVc9O#m00Z(T{i~&y7Pf)AT~$_=grPVLE6zjF1z3Jjv#JFGBdtpu zz)pbTbFiWnTt8z3y3xHJ{GP$@Sps4QczQv+1fB?n6={7)I|CIhAfAQllZWQMeoRGO z=fK^Hfc2vnt!_XcLbL6diOXDI?(4K`H%2>(r(u3c|*xlnvr51zLt znp|sWjy?I`E?t@PGD}pTqBJz$ZdUl0_=I1_MtSEY%#4=kCMfIx_azmTT^qoq{Q*3f z@K?;rN~rdpoR;^$#jt7rF_mR#Kr*9?I~bZB98$`%d25~AY!Py_LdrKqa?NbF)VEB6 z+xv_U!$WXYteRQbv`hPkj`f}>ZS!@X)uuy6TmA7@A)`Hjqj*XaI?ZZ}6}pX{x?0eu zAp3N5pAGX*>g^#|S%Xw`*~dVB8|1c+p(8g&J0QA!hWR)s>;!k0N?jYZ-U~yD7=hYe z`)GO(3im>GL|03fZ#>R64c*3Wo}F}H7c_=X_%!^NzgH4qmrg$hDPOkX;Ylddl>uY z5TTWuHP5hIu-~xP#BQiCv68Gd|8!(ioA3OHawzNucTXyamX{v{G3ND0pDsX0n&|hN z)dr;o&z^&;_6dU{v`&t=h&d2j9_6379^VkljGdnt-U{-aL(;H(GLq1u^3kJ5pAIBR?C<;Xz`623usrZuc_30A z7$(u%D)bHCx1Cv>&J0#DgBE7cTg5CcW)`cMMKiOwomqT~S*+q8qYJe8Dco_VQnTI3 z&!Z`mIhdMG1pxx2{7m3@MQ=+>q)ukQo@YMU`xO zu|RH2Lc%joXw@}!%Yfv@&|2BW@y;kO<2O7bKk6*IyWF+~k4ILMSdwNo$)KdK!~J{` zowY?T^w1$}?ptf+D@MC9Q}D*oXLSb6^W%MpH{$uIELz`zcZGbqOU|Vq$T@VkoE^>@ z6uKoeI%Ert!Q=Ip6Z498V)ivOIieRBD7*shK9%}3t#k;P(WP%wvt{k#@g>RfX-GA8 zZG?L9N>XiL7(&Q6RQhpE`mx99yU6;a2Lqaq6UFqg5V+7aB zN~CnNhUJq)tdZKkVTtf2ekOk_UV&#k@&Lx?6<_$6hWLEa)*Ejad1UL=!c~>AuY?1o zo2fzCe`A`rZL1cwFz<%^E0Eg<;^7WwlTx`c?8K-JqLytMpP$3rFbKRZmBlfk39p8o zP}~VCy4Yo*6Ze-c++Vt&w$nabm%~cZ#h7cV@{%tMUF^m=Z`Ojj8Nw4U3R2;Sbj~Tg zJz}ag=a$^r_b#~OPU*mi;P8b-O9~eY8c9IfC+kLTFdMikDSqr$PL^uM+H4==JIODr zO5Pee2y@VgyQk{Vh|3D6Ti9xWr7u-PO|kL_VfuKkmv%DomVc zMZ5t+c1Eg9yvMt%Dvd+`Km|N$V8*~Vm13#FTl~QLev~rc0ijbsw01bJc{OO0uc1vx zg$wbtz52XxnpK5S*_%#q4CF)^zZTbs(%;9u@bLU<^bH>?d$sU(bWj;1<9ZWcnuNWI zmK!5QhR6zzJv#kYFWdN1V|fwN|KiUS;%F=pBh=%Mcu2CC{(@iWS~LDrX-U#&$xpnc zDx-F=3q&I|VIJAQqRLKVsxzg#g!yrMYXV1W!p9CasU6Dah)eGXS@=x*NtkS~ye-91 z%7Byp!}3~9^ThgRq`2|V$Key!2^ngA-VVrU3FPgN-WY%T$eJDasA*0UhJkowWbw9Hf!&4DuShD=59s=-EM8gL8wr#y>>qcSnEE zv*UT!*E~O1rHTD9c;-F!dqHrYrsjdD*uvmD8vmi-2Wc9Thm63!_rcY~1(6`pH>qFx9=cCbn+NmCc=7^%tKo zV+RwUNQLDs{O2J4R2Rgw-Eq^M+%{?5O%%snH??7_Zn5t~)3>KOaC|y74acpib{y+d z7vjh}Dp@t`bBv#Wsn;%8j}OJ=Z;!zDr7G6cZ;1lPfh7KM5I?nu&d1&8!rNKuGOZ zcg{oX_k`4abvGhD^rQYhU5H%$BBaiT8mSJm5!q~sI8Ay z(Q*eyQBkMVnW?Ky97pZ^v`Q9TP14(`j$rGW-PXrNe4s{+@`}tp_Xb64*P5A+VVQIG z-Fu(C_t~#=j;mhU^`eOqE{argbZooJ{a|Gj#~~tL;*4YM?XHLDUh!8>x`F_uAD9w# zNiHcUiCg#1oWrFIaUC>8g z40)#HJktP5gecVz&G40sY*wY~Q&+|MF z-fIev``j2Foif01Et50+lt~Q#l1aiRstM*OSFn_%krXbBG)dy-oqm6iBCdi&4Rj$f zjSMUGP~9p?93>1^SAmF7XY)sg6?sQJr`j<6xv6e*cmAONGYO zt33H12eK(45-lo{%xZ;}onI6}er)cCth^uRf4)3YUhe3xiD^E~w2P}(`ThSFTevp_ zy(S^CZ>K@3BEj5XsVZnwOX%>RjYDIE$(m7_eJuBP#?E`3A#B&!hW9Nwa@g=Glxo4I zlb|#VY#JsrNt<5W$8dj{o9>Z`VagVVu9m}tPBMo=H$R3n%Q!BC6Y90Y9etwNg7`Iu zn=olcVbaiIXENt%pU$~nf3YN`c+f(>&h~4o0(tXCk zC>a;fiEHHbn3K`3znGGOOX-tqniZLuoF7hltczY+@@wOpufDms?6<}RLauIHp~{8w z4tU$wv_HqWnu8~UrC~vvh9e{pqy7G^ZFA%{y|wUEV%{cL8$17n&L!TbFn_!U4}Sk))Z%!)tNQbnKjMn%qnnZJ>krn z?#!AY#OTwxDZ-=rp{7ymfWLXr_%!ext!m?wXw(!Zi#eNYoIDk)a1xg5M~@!APHJwF zUFfIuFjt9H2&J81>%!?K*g7P$PN^33F%^#M$7!anL-z>L;Uo2#Yw0uc$E5H{aV;yC z$L@G7su$(S;-F9qRvlPwQK3G3hDQA!TXi{n+CmO1p7{$ZE<$;`Rs+8FeDGaNjJyGS zI~=%Zj0DR?4lL~iD$Yas1w$NI&KtpUfh=!LG7XH{SQXMB_N)Z{JlNZSzX0}g`FevM zd~IpqI~S8@3}9@8`Us=rVjfF^_Ji2HKCY4j%hp*g5wKjw-*x;2NYIQ{@mjEV1bH3U zJAuCrwH?3*puY3y^$p;=X>DYa)@q6XOV@W`>8?U;maZQd1SMTi+)dq8P}l+1&L$|l z4%R@EoJI~go~75p7Lde+tNc)L2FfK^(h6l~Wv#L=(Af&dA}j`|xC-Uhz;Xkf(1qr8 z(mu=fCe4(vhnEaG|*cLi!M0`G_V_M?xihtl(4yMXepg6$ek4y7&^u0uO~ zQ%o3;o1FWR^_1>~!Zxs;W8rQE+gY5>fK8Ij;eFxuO+m+5ZVn`%n=#qEpZ-em!E z3mbg1Od3)Djv@MP|A@jn7$G^}%~09~wsR5+yVr>W`kZ*g5&b(1&r%G|*ysN@Kcbqu zL)ve9M|@Mfx(zI*4;MLGw8lbtk0oKjVhwAZ*gu6&2kIQh_sCg@NzJk+a98&9)Bqpc zhRt#-w#vFwCpTQG>}r!mLeBNZmiHhh;Kq@^B(J^9*0M5)qtcypzXaCHp+@XCyrLA3 zQO`8hcADbh$&%|(9EhjU8$$&WYOsDoB$Rf5ty7}e8|Bi(TnWN~9@8*74S9RO8dSv6 z#T!qvu42&BwTyG$yAO`$VzFkWlTlhS4BNKSQ<|_fED}6}c*kJu(WEfNN-Ib>rzNZy z*J5q?iyrOK;UKY-F3V7r+Py!PFB!0Xn( zuy6sI*GwB~q$aTdkFX=l_8SKTX^}H%AsTn<2O;_=_oJ)s&_BB$UG2ETaOi#vVRz`B z{`82D0b0Y$A^rd8PsWDO!5OB8NXPn-OhZG+<1*3_+7K@2<_xh57hs6uTE-X$(w}NV z(RaU4135Pu4{d^+o9;uKFoE-o5u$CAY(WK~8kc1f)w(PzsoG^JpkWNsxh#vQo+l#Kav;T{Ba+jj3y3>b5a;8m4YLQ}-cLSI^YtGj-byv*_Sj7WXvnbhcQqBioQq zvt)$d8OTvEqiM0iq7JbPr^^(CDuft7H!ExKR1(b5=?*;W(Lw61tjlPjSQj1r#>;Y| zh_(F^MMvj4Eu0}cL_7L3n%WS1f!$`luf>vJ>4n*)VT)8^@@j1D8T3a*FZepJnjfC) zyrnj&^Nfy28u14?n`sBTQW?}}m{_zXfVYPdYIPRVsm?+=&1v=LNBGA3hWX-r@p#(a zK0t5D2WW3ovpIC7fzn%G>y>DtER{Y$ayyk?g|`uQBl(= zjdZSJ4of7&SqK_osYELfnuY^fe$Y68Zcw-|sSwe^ohYu!R|j#wK}?6@8W}1f378I! z-(xly!VD7)53_sK{JH3#wUz#pGEiA5d^==tOxcz@IVy<{to6H#Yp|7e49R?b{TA6d zeuE84Zb5M`o?C(JW^waIe>QqGf;K30!&GL5%4kry@;Syd+4@hSA| z3L1e<^!TZOWOJXPCvVQ+##M-O9PMbx(msd|K2 z+gvLI6Q*-kp&&8d(Xb7#jT;MJOO0ZdvMJtum}&byWR>6$=+v1 z^F4&vUtkxy65oENeLLEQFOR*@iMR7WfX+l89NUV|M#7#rW$NG(Rj{06FUZ0>H)niy z;S(sA&l=*&Ge**I!UyS4SI|yU_^cS0cx6TMQ-Uw)vlOyZ68G<7r=^F6kz9!l%zx}O zr3z8lZJZT3Yma;R9{B&OhxcqF%E8XpAy z*u+NsvK%As0%2N8vSZhWjFjQ6ljqTy;Cz~;8`TN=j;YcGv{X3 zol&OK%Jh>m{eY7YJECe(-xineW?Nh?{B1Z?7%k0Yj_<5E*6#;ZTVgL1-0w|#Yv zr53yF;3I!oYE}|1WB(~u%sn*B#a{}O%ksFx}>#rM2{GKQndm^CvC4Ik%*a}w7ZTYM8!2E zIqOsextfzcW0)}RMABh~3FC}LucG3V@u;F={}(6fjKoODfiF(ZM(9yO4t~*wKqcDI zcv)d0cm6u+&@PnK?{C?d(a)2fx?Vy!H^KiC(nrm8(y~w6T^?cYn6HFGV