From 5c1f8fd2626b31e951778316cac7eb49522fcce7 Mon Sep 17 00:00:00 2001 From: Robert Pengelly Date: Wed, 7 Aug 2024 04:00:13 +0100 Subject: [PATCH] Truncate and expand files when zero size is provided to int 21h/AH=40 --- build/chimaera.img | Bin 368640 -> 368640 bytes build/chimaera.vhd | Bin 34120704 -> 34120704 bytes src/apps/hello/hello.asm | 58 +++- src/kernel/fat.asm | 80 ++++- src/kernel/file.asm | 623 ++++++++++++++++++++++++++++++++++++++- src/kernel/int21.asm | 50 +++- src/kernel/kernel.asm | 6 + 7 files changed, 788 insertions(+), 29 deletions(-) diff --git a/build/chimaera.img b/build/chimaera.img index 23b8a081527111d936fcaba4d1c49da9627ee450..c557ec32ece0d8483a2638fcac5af373429a7b09 100644 GIT binary patch delta 10337 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 delta 9379 zcmcIp30zcF+rRe?%mA_}7lZ+40T~zM!pLYPIEo@@ZUd9U01Cd9ZD#ed9iJAZVcI8B^JQRGPpf8(Z4e?sB>^L5g@+8LoeF=fJpDG4bGeVSfzf4eJ{Hk6_! zPe_?IVT$4*?Y`91DHJt+`qZiM(-IW$R8W0|g}W9QNL}Zut~EaCwJOkiYERCbD|1{Y zUkb$ooH;q~;tYB{&@QSKfcar;mdksi#P9*QQWpJAtuFzs`3^pzDg6o0Q< zk=U%mqer0Fj6r@ZX)xKCNsja8#O7iv{yqxjWlZ*5$?^^H>PD_*frCzo99z;?0DVqrtCe@H`EEK~r=T ze?UmHHF%Z=r)zL3S;b@(PmsMx`~+ zoh$o*<;($VSS~_rWx3#hy=?RqZn^hcth(7?NKVngnrLNa;3IFblLvQ=6^&@UyzH%)~-vK$Z9oeYIV zw^316Xnsh#(PX8ev*|b5bcV7o?2u$-re&D+F|*oi-PKlG@3r5&%kSq;S{Sfh{)YP@ z<*D3kU5X*O;p{rj?EQCH3b>CaeS7AIX=H2YpRxM=BH><9dQ&a5?oS*Z_lWoGt4<66p^`V$-RE+nQ_ z%!0w3Yu2T3Wju?v!(}asecb+n%kBk0oBO_ z-5p68kbj>E{Ou`w%t$+DBopR{Tq$2!ag*6a4nA~K-I$qX6YG;xAFfY9mqP_*-rLBZ zyTKat%2OkU^f1?lZ(f%|d?v0H9eFC+tC+MReyw0Sf_j|B0-Nl;$Fxjhwf8Jmmy+DQPnZ=av@HIm!zWF} zd#U(5Cf!I}fzZEf;mRNsnF9vxB_;*-9t`#_M6W`&G4CAT#DB|m1gv9osOT%ILf~~8qtv10?#4z+$cnxzKE2z-?hK-C zY>;PirO2~_E2}2W+eu*|#V%5OMT*^|u##dgDLx^^CQ_{Rgrb5)Yn~nA<`|F(FOVk> zJu4021GD=U9Vl)R*DMRvW3M43Lk}ndN0z~^=;v6*9Ekcq_d3}ldTySthNe{J1g*;a z#MsuXOi2d1^x~H!D}OXkD*1|NVmFIw=LNd+Y|GDrzo4`8hO!`4k=>i-6L0Z`+nvb; z$zBQ)e|C*4gVCd3vNEMC>Ue3gjD(NQ9xXqs9!v7dR+|$qm<_*xa-hp|FE9VAb=Fb6 z*LnGOVV(J}%q8nwcxB7fW)9MUsg=o2C|F33%F{+)Sni_3Misxus63b(W!lf^@an

nEB~An?|asoSTRV| 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 diff --git a/build/chimaera.vhd b/build/chimaera.vhd index e6582f5ba99b244ea4d253666e25b7b2a31ed547..4f0093bfadd441215f898dbee5b4b661fd9829b3 100644 GIT binary patch delta 13312 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 delta 12016 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 diff --git a/src/apps/hello/hello.asm b/src/apps/hello/hello.asm index 4aac207..1e8ab64 100644 --- a/src/apps/hello/hello.asm +++ b/src/apps/hello/hello.asm @@ -8,7 +8,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Include stdio.inc. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -%include +;%include ;****************************************************************************** ; @function _main @@ -19,12 +19,66 @@ _main: mov bx, offset _msg_hello call _writestr + mov ah, HEX (39) + mov dx, offset _new_dir + int HEX (21) + jc .exit + + mov ah, HEX (3A) + mov dx, offset _new_dir + int HEX (21) + jc .exit + + mov bx, offset _msg_status + call _writestr + mov ah, HEX (3C) mov cx, HEX (20) mov dx, offset _new_file int HEX (21) jc .exit + call _writehex + call _crlf + + mov bx, ax + + mov ax, HEX (4202) + mov cx, 1024 + xor dx, dx + int HEX (21) + jc .exit + + call _writehex + call _crlf + + mov ah, HEX (40) + xor cx, cx + xor dx, dx + int HEX (21) + jc .exit + + mov ax, HEX (4200) + mov cx, 16 + xor dx, dx + int HEX (21) + jc .exit + + call _writehex + call _crlf + + mov ah, HEX (40) + xor cx, cx + xor dx, dx + int HEX (21) + jc .exit + +; mov ah, HEX (3C) +; mov cx, HEX (20) +; mov dx, offset _new_file +; int HEX (21) +; jc .exit +; ; mov ah, HEX (3C) ; mov cx, HEX (20) ; mov dx, offset _existing_file @@ -140,5 +194,7 @@ _main: ;; Data area. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; _msg_hello: db "Hello, world!", HEX (0D), HEX (0A), HEX (00) +_msg_status: db "File tests", HEX (0D), HEX (0A), HEX (00) +_new_dir: db "temp", HEX (00) _new_file: db "temp.txt", HEX (00) ;_existing_file: db "\\boot\\freeldr\\freeldr.cfg", HEX (00) diff --git a/src/kernel/fat.asm b/src/kernel/fat.asm index 4703318..61a2643 100644 --- a/src/kernel/fat.asm +++ b/src/kernel/fat.asm @@ -167,7 +167,7 @@ _find_free12: push bp mov bp, sp - sub sp, 2 + sub sp, 6 push bx push cx @@ -175,6 +175,12 @@ _find_free12: push di push es + mov ax, cs:[_fat_sector] + mov word ptr [bp - 6], ax + + mov ax, cs:[_fat_sector + 2] + mov word ptr [bp - 4], ax + mov ax, cs:[_fat_seg] mov es, ax @@ -287,13 +293,19 @@ _find_free12.next: _find_free12.error: + mov bx, word ptr [bp - 6] + mov cs:[_fat_sector], bx + + mov bx, word ptr [bp - 4] + mov cs:[_fat_sector + 2], bx + pop es pop di pop si pop cx pop bx - add sp, 2 + add sp, 6 pop bp stc @@ -301,13 +313,19 @@ _find_free12.error: _find_free12.done: + mov bx, word ptr [bp - 6] + mov cs:[_fat_sector], bx + + mov bx, word ptr [bp - 4] + mov cs:[_fat_sector + 2], bx + pop es pop di pop si pop cx pop bx - add sp, 2 + add sp, 6 pop bp clc @@ -322,7 +340,7 @@ _find_free16: push bp mov bp, sp - sub sp, 2 + sub sp, 6 push bx push cx @@ -330,6 +348,12 @@ _find_free16: push di push es + mov ax, cs:[_fat_sector] + mov word ptr [bp - 6], ax + + mov ax, cs:[_fat_sector + 2] + mov word ptr [bp - 4], ax + mov ax, cs:[_fat_seg] mov es, ax @@ -435,13 +459,19 @@ _find_free16.next: _find_free16.error: + mov bx, word ptr [bp - 6] + mov cs:[_fat_sector], bx + + mov bx, word ptr [bp - 4] + mov cs:[_fat_sector + 2], bx + pop es pop di pop si pop cx pop bx - add sp, 2 + add sp, 6 pop bp stc @@ -449,13 +479,19 @@ _find_free16.error: _find_free16.done: + mov bx, word ptr [bp - 6] + mov cs:[_fat_sector], bx + + mov bx, word ptr [bp - 4] + mov cs:[_fat_sector + 2], bx + pop es pop di pop si pop cx pop bx - add sp, 2 + add sp, 6 pop bp clc @@ -470,7 +506,7 @@ _find_free32: push bp mov bp, sp - sub sp, 2 + sub sp, 6 push bx push cx @@ -478,6 +514,12 @@ _find_free32: push di push es + mov ax, cs:[_fat_sector] + mov word ptr [bp - 6], ax + + mov ax, cs:[_fat_sector + 2] + mov word ptr [bp - 4], ax + mov ax, cs:[_fat_seg] mov es, ax @@ -571,13 +613,19 @@ _find_free32.next: _find_free32.error: + mov bx, word ptr [bp - 6] + mov cs:[_fat_sector], bx + + mov bx, word ptr [bp - 4] + mov cs:[_fat_sector + 2], bx + pop es pop di pop si pop cx pop bx - add sp, 2 + add sp, 6 pop bp stc @@ -585,13 +633,19 @@ _find_free32.error: _find_free32.done: + mov bx, word ptr [bp - 6] + mov cs:[_fat_sector], bx + + mov bx, word ptr [bp - 4] + mov cs:[_fat_sector + 2], bx + pop es pop di pop si pop cx pop bx - add sp, 2 + add sp, 6 pop bp clc @@ -797,13 +851,13 @@ _nextcluster_fat12.even_cluster: _nextcluster_fat12.compare: + xor dx, dx + cmp ax, HEX (0FF8) cmc _nextcluster_fat12.done: - xor dx, dx - pop si pop cx ret @@ -887,13 +941,13 @@ _nextcluster_fat16.first64: _nextcluster_fat16.compare: + xor dx, dx + cmp ax, HEX (FFF8) cmc _nextcluster_fat16.done: - xor dx, dx - pop si pop cx ret diff --git a/src/kernel/file.asm b/src/kernel/file.asm index 0c73b04..2b67d1f 100644 --- a/src/kernel/file.asm +++ b/src/kernel/file.asm @@ -5,6 +5,11 @@ % define HEX(y) 0x##y %endif +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Include our fat.inc. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +%include "fat.inc" + ;****************************************************************************** ; @function _read_cluster ;****************************************************************************** @@ -1135,7 +1140,7 @@ _seek_file.ptr_ok: _seek_file.done: - mov word ptr es:[si + 52], 1 + mov word ptr es:[si + 54], 1 mov ax, es:[si + 62] mov dx, es:[si + 64] @@ -1148,6 +1153,622 @@ _seek_file.done: ret +;****************************************************************************** +; @function _write_file +;****************************************************************************** +global _write_file +_write_file: + + push bp + + mov bp, sp + sub sp, 12 + + push bx + push cx + push dx + push si + push di + push es + push ds + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Make sure our total bytes read is zero. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov word ptr [bp - 2], 0 + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Make sure we're not write-only. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + cmp word ptr es:[si + 56], 0 + je _write_file.error + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; If theres zero byte to write then truncate/extend. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + and cx, cx + jz _write_file.zero + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; For now we'll jump to error + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + jmp _write_file.error + +_write_file.zero: + + mov ax, es:[si + 66] + mov dx, es:[si + 68] + + cmp dx, es:[si + 64] + ja _write_file.truncate + + cmp dx, es:[si + 64] + jne _write_file.extend + + cmp ax, es:[si + 62] + jb _write_file.extend + +_write_file.truncate: + + mov bx, es:[si + 58] + or bx, es:[si + 60] + + and bx, bx + jz _write_file.done + + mov cx, es:[si + 50] + div cx + + mov bx, ax + + mov ax, es:[si + 62] + mov dx, es:[si + 64] + + mov cx, es:[si + 50] + div cx + + mov cx, ax + xchg bx, cx + + mov ax, es:[si + 58] + mov dx, es:[si + 60] + +_write_file.truncate_walk: + + mov word ptr [bp - 6], ax + mov word ptr [bp - 4], dx + + and bx, bx + jz _write_file.truncate_ok + + call cs:[_next_cluster] + jc _write_file.truncate_ok + + dec cx + + dec bx + jnz _write_file.truncate_walk + +_write_file.truncate_ok: + + mov ax, word ptr [bp - 6] + mov dx, word ptr [bp - 4] + + mov word ptr [bp - 12], cx + +_write_file.truncate_loop: + + and cx, cx + jz _write_file.truncate_done + + call cs:[_next_cluster] + jc _write_file.truncate_done + + push si + push di + + mov si, ax + mov di, dx + + mov ax, word ptr [bp - 6] + mov dx, word ptr [bp - 4] + + mov word ptr [bp - 6], si + mov word ptr [bp - 4], di + + pop di + pop si + + push bx + push cx + + xor bx, bx + xor cx, cx + + call cs:[_update_cluster] + + pop cx + pop bx + + mov ax, word ptr [bp - 6] + mov dx, word ptr [bp - 4] + + dec cx + jnz _write_file.truncate_loop + +_write_file.truncate_done: + + mov ax, word ptr [bp - 6] + mov dx, word ptr [bp - 4] + + push bx + push cx + + xor bx, bx + xor cx, cx + + call cs:[_update_cluster] + + pop cx + pop bx + + xor ax, ax + xor dx, dx + + mov bx, es:[si + 62] + or bx, es:[si + 64] + + and bx, bx + jz _write_file.truncate_update + + mov ax, es:[si + 58] + mov dx, es:[si + 60] + + push bx + push cx + + mov bx, HEX (FFFF) + mov cx, HEX (FFF8) + + call cs:[_update_cluster] + + pop cx + pop bx + + dec word ptr [bp - 12] + +_write_file.truncate_update: + + mov es:[si + 58], ax + mov es:[si + 60], dx + + mov ax, es:[si + 58] + mov word ptr [bp - 6], ax + + mov ax, es:[si + 60] + mov word ptr [bp - 4], ax + + mov ax, es:[si + 62] + mov dx, es:[si + 64] + + mov es:[si + 66], ax + mov word ptr [bp - 10], ax + + mov es:[si + 68], dx + mov word ptr [bp - 8], dx + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Update the entry on disk. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ax, es:[si + 74] + mov dx, es:[si + 76] + + mov cx, es:[si + 78] + mov di, es:[si + 80] + + push es + push bx + push ax + push dx + push cx + + mov bx, cs:[_disk_scratch] + mov es, bx + + xor bx, bx + call _read_sectors + + mov ax, word ptr [bp - 6] + mov es:[di + 26], ax + + mov ax, word ptr [bp - 4] + mov es:[di + 20], ax + + mov ax, word ptr [bp - 10] + mov es:[di + 28], ax + + mov ax, word ptr [bp - 8] + mov es:[di + 30], ax + + pop cx + pop dx + pop ax + + xor bx, bx + call _write_sectors + + pop bx + pop es + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Check if we have an info sector. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ax, cs:[_info_sector] + + and ax, ax + jz _write_file.done + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Update the free clusters. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + xor dx, dx + + add ax, cs:[_hidden_sectors] + adc dx, cs:[_hidden_sectors + 2] + + mov bx, cs:[_disk_scratch] + mov es, bx + xor bx, bx + + mov cx, 1 + call _read_sectors + + mov di, HEX (01E0) + + mov ax, es:[di + 8] + mov dx, es:[di + 10] + + add ax, word ptr [bp - 12] + adc dx, 0 + + mov es:[di + 8], ax + mov es:[di + 10], dx + + mov ax, cs:[_info_sector] + xor dx, dx + + add ax, cs:[_hidden_sectors] + adc dx, cs:[_hidden_sectors + 2] + + mov cx, 1 + call _write_sectors + + jmp _write_file.done + +_write_file.extend: + + push es + push di + push ax + + xor cx, es:[si + 50] + + mov ax, cs:[_disk_scratch] + mov es, ax + xor di, di + + xor al, al + rep stosb + + pop ax + pop di + pop es + + mov cx, es:[si + 50] + div cx + + mov bx, ax + + mov ax, es:[si + 62] + mov dx, es:[si + 64] + + mov cx, es:[si + 50] + div cx + + mov cx, ax + + mov ax, es:[si + 58] + mov dx, es:[si + 60] + + mov di, ax + or di, dx + + and di, di + jnz _write_file.extend_walk + + call cs:[_find_free] + jc _write_file.done + + mov word ptr [bp - 6], ax + mov word ptr [bp - 4], dx + + mov es:[si + 58], ax + mov es:[si + 60], dx + + push bx + push cx + call cs:[_convert_cluster] + + pop cx + pop bx + jc _write_file.done + + push es + push bx + push cx + + xor ch, ch + mov cl, cs:[_sectors_per_cluster] + + mov bx, cs:[_disk_scratch] + mov es, bx + + xor bx, bx + call _write_sectors + + pop cx + pop bx + pop es + + jmp _write_file.extend_no_walk + +_write_file.extend_walk: + + mov word ptr [bp - 6], ax + mov word ptr [bp - 4], dx + + and bx, bx + jz _write_file.extend_no_walk + + call cs:[_next_cluster] + jc _write_file.extend_no_walk + + dec cx + + dec bx + jnz _write_file.extend_walk + +_write_file.extend_no_walk: + + mov ax, word ptr [bp - 6] + mov dx, word ptr [bp - 4] + + mov word ptr [bp - 12], cx + +_write_file.extend_loop: + + and cx, cx + jz _write_file.extend_update + + call cs:[_find_free] + jc _write_file.done + + push bx + push cx + + mov bx, dx + mov cx, ax + + mov ax, word ptr [bp - 6] + mov dx, word ptr [bp - 4] + + call cs:[_update_cluster] + + push bx + push cx + call cs:[_convert_cluster] + + pop cx + pop bx + jc _write_file.extend_update + + push es + push bx + push cx + + xor ch, ch + mov cl, cs:[_sectors_per_cluster] + + mov bx, cs:[_disk_scratch] + mov es, bx + + xor bx, bx + call _write_sectors + + pop cx + pop bx + pop es + + mov word ptr [bp - 6], cx + mov word ptr [bp - 4], bx + + pop cx + pop bx + + dec cx + jnz _write_file.extend_loop + +_write_file.extend_update: + + push es + push bx + push cx + + mov bx, HEX (FFFF) + mov cx, HEX (FFF8) + + mov ax, word ptr [bp - 6] + mov dx, word ptr [bp - 4] + + call cs:[_update_cluster] + + call cs:[_convert_cluster] + jc _write_file.done + + xor ch, ch + mov cl, cs:[_sectors_per_cluster] + + mov bx, cs:[_disk_scratch] + mov es, bx + + xor bx, bx + call _write_sectors + + pop cx + pop bx + pop es + + mov ax, es:[si + 58] + mov word ptr [bp - 6], ax + + mov ax, es:[si + 60] + mov word ptr [bp - 4], ax + + mov ax, es:[si + 62] + mov dx, es:[si + 64] + + mov es:[si + 66], ax + mov word ptr [bp - 10], ax + + mov es:[si + 68], dx + mov word ptr [bp - 8], dx + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Update the entry on disk. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ax, es:[si + 74] + mov dx, es:[si + 76] + + mov cx, es:[si + 78] + mov di, es:[si + 80] + + push es + push bx + push ax + push dx + push cx + + mov bx, cs:[_disk_scratch] + mov es, bx + + xor bx, bx + call _read_sectors + + mov ax, word ptr [bp - 6] + mov es:[di + 26], ax + + mov ax, word ptr [bp - 4] + mov es:[di + 20], ax + + mov ax, word ptr [bp - 10] + mov es:[di + 28], ax + + mov ax, word ptr [bp - 8] + mov es:[di + 30], ax + + pop cx + pop dx + pop ax + + xor bx, bx + call _write_sectors + + pop bx + pop es + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Check if we have an info sector. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ax, cs:[_info_sector] + + and ax, ax + jz _write_file.done + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Update the free clusters. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + xor dx, dx + + add ax, cs:[_hidden_sectors] + adc dx, cs:[_hidden_sectors + 2] + + mov bx, cs:[_disk_scratch] + mov es, bx + xor bx, bx + + mov cx, 1 + call _read_sectors + + mov di, HEX (01E0) + + mov ax, es:[di + 8] + mov dx, es:[di + 10] + + sub ax, word ptr [bp - 12] + sbb dx, 0 + + mov es:[di + 8], ax + mov es:[di + 10], dx + + mov ax, cs:[_info_sector] + xor dx, dx + + add ax, cs:[_hidden_sectors] + adc dx, cs:[_hidden_sectors + 2] + + mov cx, 1 + call _write_sectors + +_write_file.done: + + mov word ptr es:[si + 54], 1 + + pop ds + pop es + pop di + pop si + pop dx + pop cx + pop bx + + add sp, 12 + clc + + mov ax, word ptr [bp - 2] + pop bp + + ret + +_write_file.error: + + mov word ptr es:[si + 54], 1 + + pop ds + pop es + pop di + pop si + pop dx + pop cx + pop bx + + add sp, 12 + stc + + mov ax, 5 + pop bp + + ret + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Data area. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/kernel/int21.asm b/src/kernel/int21.asm index 8a0b2ae..7e3899a 100644 --- a/src/kernel/int21.asm +++ b/src/kernel/int21.asm @@ -331,10 +331,8 @@ _get_disk_info.fat32: _get_disk_info.done: - xor ax, ax - - mov cs:[_fat_sector], ax - mov cs:[_fat_sector + 2], ax + mov word ptr cs:[_fat_sector], 0 + mov word ptr cs:[_fat_sector + 2], 0 pop ds pop es @@ -1907,7 +1905,7 @@ _int21_3A.clear: inc cx mov ax, si - mov dx, si + mov dx, di jmp _int21_3A.clear @@ -1981,7 +1979,7 @@ _int21_3A.clear_final: mov ax, cs:[_info_sector] and ax, ax - jz _int21_41.done + jz _int21_3A.done ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Update the free clusters. @@ -2251,6 +2249,9 @@ _int21_3B.fat32: _int21_3B.get_path: + mov word ptr cs:[_fat_sector], 0 + mov word ptr cs:[_fat_sector + 2], 0 + mov di, si push es @@ -2599,6 +2600,8 @@ _int21_3C: _int21_3C.open: + mov ax, HEX (3D02) + call _open_file jnc _int21_3C.zero @@ -2651,6 +2654,8 @@ _int21_3C.create: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Try and open the file again. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ax, HEX (3D02) + call _open_file jc _int21_3C.error @@ -3151,6 +3156,9 @@ _int21_3F.fat32: _int21_3F.read: + mov word ptr cs:[_fat_sector], 0 + mov word ptr cs:[_fat_sector + 2], 0 + pop cx pop ax pop ds @@ -3211,7 +3219,7 @@ _int21_40: ;; If stdin was passed then we can't write to it. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; and bx, bx - jz _int21_40.error + jz _int21_40.invalid ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Otherwise, lets write the bytes. @@ -3235,13 +3243,13 @@ _int21_40.check: ;; Check if we have any open files. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmp word ptr cs:[_vec_files + 2], 0 - je _int21_40.error + je _int21_40.invalid ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Make sure we have a valid file handle. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmp bx, 3 - jb _int21_40.error + jb _int21_40.invalid ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Get the correct file offset by subtracting 3. @@ -3275,7 +3283,7 @@ _int21_40.check: ;; If the vector entry is zero then the file handle is invalid. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmp word ptr es:[bx], 0 - je _int21_40.error + je _int21_40.invalid ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Re-initialize the extra segment but this time with the address @@ -3290,8 +3298,8 @@ _int21_40.copy: push ax push cx - mov ds, ax xor si, si + mov ds, ax lodsw mov cs:[_curr_cluster], ax @@ -3372,12 +3380,26 @@ _int21_40.fat32: _int21_40.write: + mov word ptr cs:[_fat_sector], 0 + mov word ptr cs:[_fat_sector + 2], 0 + pop cx pop ax pop ds pop si mov es, ax + xor si, si + + call _write_file + jc _int21_40.error + + jmp _int21_40.done + +_int21_40.invalid: + + mov ax, 6 + stc _int21_40.error: @@ -3390,9 +3412,6 @@ _int21_40.error: pop bx pop bp - mov ax, 6 - stc - jmp iretc _int21_40.done: @@ -4580,6 +4599,9 @@ _int21_4F.fat32: _int21_4F.find: + mov word ptr cs:[_fat_sector], 0 + mov word ptr cs:[_fat_sector + 2], 0 + pop bx pop cx diff --git a/src/kernel/kernel.asm b/src/kernel/kernel.asm index dc23c0f..331a054 100644 --- a/src/kernel/kernel.asm +++ b/src/kernel/kernel.asm @@ -619,6 +619,12 @@ _check_disks: mul cx stosw + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; No info sector. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + xor ax, ax + stosw + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; We don't want to set the selected drive so jump to getting the ;; hard disk paritions. -- 2.34.1