From 93dcfe9610913b14bb9afe5326442dcfbe44e16f Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Sat, 7 Oct 2023 15:15:10 -0700 Subject: [PATCH] Slice Protection, Issue #366 - Dean Jenkins has motivated me to implement additional protection from using a slice that does not fit within the capacity of the physical disk being used. You can still assign an unusable slice, but when you try to refer to it, you will immediately get a "no disk" error from the OS. --- Source/CBIOS/cbios.asm | 90 +++++++++++++++++++++++++++++++++++------- Source/CPM3/diskio.z80 | 50 ++++++++++++++++++++++- Source/ver.inc | 2 +- Source/ver.lib | 2 +- 4 files changed, 126 insertions(+), 18 deletions(-) diff --git a/Source/CBIOS/cbios.asm b/Source/CBIOS/cbios.asm index 805ef457..e6690f72 100644 --- a/Source/CBIOS/cbios.asm +++ b/Source/CBIOS/cbios.asm @@ -1511,8 +1511,8 @@ DSK_MBR3: ; DSK_MBR4: ; IF BOOT FROM PARTITION, USE NEW SECTORS PER SLICE VALUE - LD HL,16384 ; NEW SECTORS PER SLICE - LD (SPS),HL ; SAVE IT + LD HL,16384 ; NEW SECTORS PER SLICE + LD (SPS),HL ; SAVE IT ; UPDATE MEDIA ID LD A,MID_HDNEW ; NEW MEDIA ID @@ -1520,20 +1520,79 @@ DSK_MBR4: ; DSK_MBR5: ; ADJUST LBA OFFSET BASED ON TARGET SLICE - LD A,(SLICE) ; GET SLICE, A IS LOOP CNT - LD HL,(SEKLBA) ; SET DE:HL - LD DE,(SEKLBA+2) ; ... TO STARTING LBA - LD BC,(SPS) ; SECTORS PER SLICE -DSK_MBR6: - OR A ; SET FLAGS TO CHECK LOOP CNTR - JR Z,DSK_MBR8 ; DONE IF COUNTER EXHAUSTED - ADD HL,BC ; ADD ONE SLICE TO LOW WORD - JR NC,DSK_MBR7 ; CHECK FOR CARRY - INC DE ; IF SO, BUMP HIGH WORD -DSK_MBR7: - DEC A ; DEC LOOP DOWNCOUNTER - JR DSK_MBR6 ; AND LOOP + LD A,(SLICE) ; GET SLICE, A IS LOOP CNT + LD HL,(SEKLBA) ; SET DE:HL + LD DE,(SEKLBA+2) ; ... TO STARTING LBA + LD BC,(SPS) ; SECTORS PER SLICE +DSK_MBR6: + OR A ; SET FLAGS TO CHECK LOOP CNTR + JR Z,DSK_MBR8 ; DONE IF COUNTER EXHAUSTED + ADD HL,BC ; ADD ONE SLICE TO LOW WORD + JR NC,DSK_MBR7 ; CHECK FOR CARRY + INC DE ; IF SO, BUMP HIGH WORD +DSK_MBR7: + DEC A ; DEC LOOP DOWNCOUNTER + JR DSK_MBR6 ; AND LOOP DSK_MBR8: + ; LBA OFFSET OF DESIRED SLICE IS NOW IN DE:HL + ; NEED TO CHECK IF THE SLICE IS BEYOND CAPACITY OF MEDIA + ; IF LBA_OFF + SPS >= DSK_CAP, ERROR! + + ; SAVE LBA_OFF + PUSH DE ; MSW + PUSH HL ; LSW + + ; ADD SPS TO COMPUTE LBA_REQ + LD BC,(SPS) ; SECTORS PER SLICE + ADD HL,BC ; ADD ONE SLICE TO LOW WORD + JR NC,DSK_MBR9 ; CHECK FOR CARRY + INC DE ; IF SO, BUMP HIGH WORD +DSK_MBR9: + ; SAVE CAP_REQ + LD (CAP_REQ),HL ; LSW + LD (CAP_REQ+2),DE ; MSW +; +#IFDEF PLTWBW + ; GET DSK_CAP (DE:HL) + LD B,BF_DIOCAP ; HBIOS DISK CAPACITY FUNC + LD A,(SEKUNIT) ; DISK UNIT NUMBER + LD C,A ; ... INTO C + RST 08 ; HBIOS CALL (DE:HL = CAPACITY) +#ENDIF +; +#IFDEF PLTUNA + ; GET DSK_CAP (DE:HL) + LD C,$45 ; UBIOS DISK INFO FUNC + LD A,(SEKUNIT) ; DISK UNIT NUMBER + LD B,A ; ... INTO B + RST 08 ; CALL UNA (DE:HL = CAPACITY) +#ENDIF +; + ; SAVE DSK_CAP (DE:HL) + PUSH DE ; SAVE DSK_CAP (MSW) + PUSH HL ; SAVE DSK_CAP (LSW) +; + ; CHECK DSK_CAP >= CAP_REQ, CF SET ON OVERFLOW + ; NO NEED SAVE ACTUAL RESULT + OR A ; CLEAR CARRY FOR SBC + POP HL ; DSK_CAP LSW + LD DE,(CAP_REQ) ; CAP_REQ LSW + SBC HL,DE ; DSK_CAP - LBA_REQ (LSW) + POP HL ; DSK_CAP MSW + LD DE,(CAP_REQ+2) ; CAP_REQ MSW + SBC HL,DE ; DSK_CAP - LBA_REQ (MSW) +; + ; RESTORE LBA_OFF + POP HL ; LSW + POP DE ; MSW +; + ; ABORT ON OVERFLOW WITH ERROR! + JR NC,DSK_MBR10 ; IF NO OVERFLOW, CONTINUE + OR $FF ; SIGNAL ERROR + RET ; DONE +; +DSK_MBR10: + ; FINALIZE SLICE LBA SET 7,D ; SET LBA ACCESS FLAG ; RESAVE IT LD (SEKLBA),HL ; LOWORD @@ -1758,6 +1817,7 @@ CCPBUF .DW 0 ; ADDRESS OF CCP BUF IN BIOS BANK MEDID .DB 0 ; TEMP STORAGE FOR MEDIA ID SLICE .DB 0 ; CURRENT SLICE SPS .DW 0 ; SECTORS PER SLICE +CAP_REQ .DW 0,0 ; LBA CAP REQUIRED FOR SLICE STKSAV .DW 0 ; TEMP SAVED STACK POINTER ; #IFDEF PLTWBW diff --git a/Source/CPM3/diskio.z80 b/Source/CPM3/diskio.z80 index 08ee1554..8808751b 100644 --- a/Source/CPM3/diskio.z80 +++ b/Source/CPM3/diskio.z80 @@ -38,7 +38,7 @@ extrn ?bnkxlt - extrn phex8, cout + extrn phex16, phex8, cout, crlf, crlf2 ; CP/M 3 Disk definition macros @@ -600,6 +600,53 @@ boot7: dec a ; dec loop downcounter jr boot6 ; and loop boot8: + + ; LBA offset of desired slice is now in DE:HL. + ; Need to check if the slice is beyond capacity of media. + ; If lba_off + sps >= dsk_cap, error! + + ; Save lba_off + push de ; msw + push hl ; lsw + + ; Add sps to compute lba_req + ld bc,(sps) ; sectors per slice + add hl,bc ; add one slice to low word + jr nc,dsk_mbr9 ; check for carry + inc de ; if so, bump high word +dsk_mbr9: + ; Save cap_req + ld (cap_req),hl ; lsw + ld (cap_req+2),de ; msw + + ; Get dsk_cap (de:hl) + ld b,1Ah ; hbios disk capacity func + ld a,(unit) ; disk unit number + ld c,a ; ... into c + rst 08 ; hbios call (de:hl = capacity) + + ; Save dsk_cap (de:hl) + push de ; save dsk_cap (msw) + push hl ; save dsk_cap (lsw) + + ; Check dsk_cap >= cap_req, cf set on overflow + ; No need save actual result + or a ; clear carry for sbc + pop hl ; dsk_cap lsw + ld de,(cap_req) ; cap_req lsw + sbc hl,de ; dsk_cap - lba_req (lsw) + pop hl ; dsk_cap msw + ld de,(cap_req+2) ; cap_req msw + sbc hl,de ; dsk_cap - lba_req (msw) + + ; Restore lba_off + pop hl ; lsw + pop de ; msw + + ; Abort on overflow with error! + jp c,err_noslice ; slice too high, error exit + + ; Finalize slice lba set 7,d ; set LBA access flag ld (lba),hl ; save new lba, low word ld (lba+2),de ; save new lba, high word @@ -870,6 +917,7 @@ unit db 0 ; working disk unit num slice db 0 ; working slice num lba dw 0,0 ; working lba sps dw 0 ; sectors per slice +cap_req dw 0,0 ; lba cap required for slice mbrsec ds 512 ; MBR sector buffer dma dw 0 ; current DMA address bank db 0 ; HBIOS DMA bank diff --git a/Source/ver.inc b/Source/ver.inc index 0962c624..a6b9cd84 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,7 +2,7 @@ #DEFINE RMN 4 #DEFINE RUP 0 #DEFINE RTP 0 -#DEFINE BIOSVER "3.4.0-dev.1" +#DEFINE BIOSVER "3.4.0-dev.2" #define rmj RMJ #define rmn RMN #define rup RUP diff --git a/Source/ver.lib b/Source/ver.lib index 24dd9054..37db20ef 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 4 rup equ 0 rtp equ 0 biosver macro - db "3.4.0-dev.1" + db "3.4.0-dev.2" endm