source: trunk/BOOTCODE/REGULAR/DRIVEIO.ASM@ 37

Last change on this file since 37 was 37, checked in by Ben Rietbroek, 11 years ago

Reworked Build Environment [2012-02-15]

WARNING!!

All commits upto and including the commit of [2012-05-13] contain
a severe bug!! Building from these sources and then disabling
the 'force LBA' feature while also using the drive-letter feature or
editing the label can DESTROY THE MBR on ALL ATTACHED DISKS!!
DO NOT DISABLE 'FORCE LBA USAGE' WHEN BUILT FROM THE THESE COMMITS!!

Changes

o Reworked build environment
o Start made with coding FIXCODE in C
o Moved MBR protection image
o New overlap macro
o Protect type 0x35 from edit (user popup)
o Protect type 0x35 from adding to menu (user popup)
o More...
! No LVM Label change yet

Note

o Changed license to GPL v3

See file COPYING in trunk.

File size: 41.7 KB
Line 
1; AiR-BOOT (c) Copyright 1998-2008 M. Kiewitz
2;
3; This file is part of AiR-BOOT
4;
5; AiR-BOOT is free software: you can redistribute it and/or modify it under
6; the terms of the GNU General Public License as published by the Free
7; Software Foundation, either version 3 of the License, or (at your option)
8; any later version.
9;
10; AiR-BOOT is distributed in the hope that it will be useful, but WITHOUT ANY
11; WARRANTY: without even the implied warranty of MERCHANTABILITY or FITNESS
12; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13; details.
14;
15; You should have received a copy of the GNU General Public License along with
16; AiR-BOOT. If not, see <http://www.gnu.org/licenses/>.
17;
18;---------------------------------------------------------------------------
19; AiR-BOOT / DRIVE I/O
20;---------------------------------------------------------------------------
21
22
23
24IFDEF ModuleNames
25DB 'DRIVEIO',0
26ENDIF
27
28; Note: Some routines set DS/ES to CS or even address via CS, even if its not
29; needed. This was done for SECURITY. So DO NOT remove it.
30; Its there to make sure the correct data is loaded/written to/from
31; harddrive.
32;
33; IF YOU MODIFY ANYTHING IN HERE, YOU MAY EASILY BREAK YOUR HARDDRIVE!
34
35; Will only load base-configuration, will NOT load IPT nor Hide-Config
36; Those are originally loaded on startup and will NOT get reloaded.
37DriveIO_LoadConfiguration Proc Near Uses ax bx cx dx es
38 mov ax, cs
39 mov es, ax
40 mov bx, offset Configuration
41 mov dx, 0080h ; First harddrive, Sector 55...
42 mov cx, 0037h
43 mov ax, 0201h ; Function 02, read 1 sector...
44 int 13h
45 jnc DIOLC_NoError
46 call MBR_LoadError ; Will Abort BootUp
47 DIOLC_NoError:
48 ret
49DriveIO_LoadConfiguration EndP
50
51DriveIO_SaveConfiguration Proc Near Uses ax bx cx dx ds es si
52 mov ax, cs
53 mov ds, ax
54 mov es, ax ; Safety first (CS==DS==ES)
55 ; --- Overwrite Floppy-Name with "FloppyDrive"
56 mov si, offset TXT_Floppy_Drive
57 mov di, offset PartitionTable
58 sub di, 30 ; Adjust to Floppy-Name
59 mov cx, 11
60 rep movsb
61 mov si, offset Configuration ; Calculate new checksum
62 xor bx, bx
63
64 ; Changed from 5 to calculated value (not here, see compat. issue below)
65 ; Fixes issue: #2987 -- "air-boot doesn't remember drive letter"
66 ; Size of the ab-configuration in 512 byte sectors
67 ;mov cx, (MBR_BackUpMBR - Configuration) / 200h
68
69 ; AB v1.07 stores a 5 sector configuration with a 5 sector checksum.
70 ; AB v1.0.8 *should* stores a 7 sector configuration with a
71 ; 7 sector checksum.
72 ; Because 5 was hardcoded here, SET(A)BOOT v1.07 will see see an AB v1.0.8
73 ; config as corrupted, while this is not the case.
74 ; So, for compatibility reasons, in v1.0.8, the checksum stored is over
75 ; 5 sectors, to be compatible with v1.07.
76 ; This may change (be corrected) in future versions !
77 mov cx,5
78
79 mov dx, [CFG_CheckConfig]
80 mov [CFG_CheckConfig], bx
81 DIOSC_Loop:
82 call MBR_GetCheckOfSector
83 loop DIOSC_Loop
84 mov [CFG_CheckConfig], bx
85 ; --------------------------------------------------------------------
86 ; ES == CS
87 mov bx, offset Configuration
88 mov dx, 0080h ; First harddrive, Sector 55...
89 mov cx, 0037h
90
91 ; Changed from 5 to calculated value
92 ; Fixes issue: #2987 -- "air-boot doesn't remember drive letter"
93 ; Size of the ab-configuration in 512 byte sectors
94 mov al, (MBR_BackUpMBR - Configuration) / 200h
95 mov ah,03h
96
97 int 13h
98 jnc DIOSC_NoError
99 call MBR_SaveError ; Will Abort BootUp
100 DIOSC_NoError:
101 ret
102DriveIO_SaveConfiguration EndP
103
104DriveIO_UpdateFloppyName Proc Near Uses bx cx dx ds si es di
105 mov ax, cs
106 mov ds, ax
107 mov es, ax
108
109 mov ah, 00h ; Function 2 - Reset Drive
110 xor dl, dl
111 int 13h
112 xor dx, dx ; Cylinder=0, Head=0
113 mov cx, 1 ; Sector=1, Drive=0
114 mov bx, offset TmpSector ; ES:BX - TmpSector
115 mov ax, 0201h ; Function 2 - Load Sector
116 int 13h
117 jnc DIOUFN_AllFine
118
119 ; --- Overwrite Floppy-Name with "No Disc"
120 mov si, offset TXT_Floppy_NoDisc
121 xor ax, ax
122 DIOUFN_WriteFloppyName:
123 mov di, offset PartitionTable
124 sub di, 30 ; Adjust to Floppy-Name
125 mov cl, 11
126 rep movsb
127 ret ; AX=-1 -> GotDisc, =0 -> NoDisc
128
129 ; --- Floppy found and read, data in TempSector
130 DIOUFN_AllFine:
131 mov ax, -1
132 mov si, offset TXT_Floppy_NoName
133 cmp wptr es:[bx+54], 'AF'
134 jne DIOUFN_WriteFloppyName
135 cmp wptr es:[bx+56], '1T'
136 jne DIOUFN_WriteFloppyName
137 cmp bptr es:[bx+58], '2'
138 jne DIOUFN_WriteFloppyName
139 mov si, bx
140 add si, 43 ; FAT12 - Volume Label Location
141 jmp DIOUFN_WriteFloppyName
142DriveIO_UpdateFloppyName EndP
143
144; =============================================================================
145; HARDDRIVE / GENERAL ACCESS
146; =============================================================================
147; The following routines are used for harddisc/floppy access.
148; The access is done via INT 13h/CHS or INT 13h/LBA.
149; Access will be done prefered by INT 13h/CHS, because it's (I wonder!) much
150; faster, than the LBA-method. I don't know, why LBA is so slow. Perhaps BIOS.
151;
152; Internal access (to AiR-BOOT) is always done via INT 13h/CHS.
153
154DriveIO_GetHardDriveCount Proc Near Uses ds si
155 push ds
156 push si
157 push 0040h
158 pop ds
159 mov si, 0075h
160 mov dh, ds:[si] ; 40:75 -> POST: Total Harddiscs == DL
161 pop si
162 pop ds
163 mov TotalHarddiscs, dh
164 ret
165DriveIO_GetHardDriveCount EndP
166
167
168; Fills our LBA-Usage table. It holds the LBA-address, where BIOS/CHS access is
169; stopped and BIOS/LBA access is started.
170; This is calculated by Sector*Heads. Comparing will get done with Bit 25-10
171; on LBA sectors, so we actually divide sector number by 1024.
172DriveIO_InitLBASwitchTable Proc Near Uses es di
173 mov di, offset LBASwitchTable
174 mov dh, TotalHarddiscs
175 mov dl, 80h
176 DIOILUT_DriveLoop:
177 push dx
178 push di
179 mov ah, 08h
180 int 13h ; DISK - GET DRIVE PARAMETERS
181 mov ah, 0FBh ; Assume 255 heads/63 sectors, if error
182 jc DIOILUT_Error
183 and cl, 111111b ; Isolate lower 6 bits of CL -> sector count
184
185 ;movzx ax, cl
186 mov al,cl
187 mov ah,0
188
189 mov bl, dh ; DH -> max head number
190 mul bl ; AX = Sectors*Heads
191 shl ah, 1
192 shl ah, 1 ; Shift 2 bits, so we are able to compare to
193 ; bit 16-23 of the LBA address
194 DIOILUT_Error:
195 pop di
196 pop dx
197 mov bptr ds:[di], ah ; Save that value
198 inc di ; Go to next BYTE
199 inc dl
200 dec dh
201 jnz DIOILUT_DriveLoop
202 ret
203DriveIO_InitLBASwitchTable EndP
204
205
206
207
208; Adjusts BX:AX / CX:DX to meet LVM sector location
209; Destroys SI
210; Rousseau: Enhanced to handle sector-numbers 127 and 255 besides 63 for LVM-info sectors.
211; Ugly, need to cleanup.
212DriveIO_LVMAdjustToInfoSector Proc Near
213
214
215
216; pusha
217; call AuxIO_TeletypeNL
218
219 ; LBA
220; xchg dx,bx
221; call AuxIO_TeletypeHexDWord
222; call AuxIO_TeletypeNL
223; xchg bx,dx
224
225 ; CYL
226; mov al,ch
227; call AuxIO_TeletypeHexByte
228; call AuxIO_TeletypeNL
229
230 ; HEAD
231; mov al,dh
232; call AuxIO_TeletypeHexByte
233; call AuxIO_TeletypeNL
234
235 ; SEC
236; mov al,cl
237; call AuxIO_TeletypeHexByte
238; call AuxIO_TeletypeNL
239
240 ; DRIVE
241; mov al,dl
242; call AuxIO_TeletypeHexByte
243; call AuxIO_TeletypeNL
244
245; popa
246
247
248 ;local ts:word
249 ;local ts2:word
250
251 pusha
252
253 ; Dump drive
254 mov si,offset drive
255; call AuxIO_Print
256 xchg al,dl
257; call AuxIO_TeletypeHexByte
258; call AuxIO_TeletypeNL
259 xchg dl,al
260
261 ; Dump SPT
262 mov si,offset spt_used
263; call AuxIO_Print
264 push dx
265 push bx
266 xor dh,dh
267 and dl,01111111b
268 shl dx,1
269 shl dx,1
270 mov bx, offset TrueSecs
271 add bx,dx
272 mov ax,word ptr [bx]
273
274 ;mov [ts],ax
275
276; call AuxIO_TeletypeHexWord
277; call AuxIO_TeletypeNL
278 pop bx
279 pop dx
280
281 pusha
282 push dx
283 ; Location of extended position
284 mov dx,word ptr [ExtendedAbsPos+02]
285 mov ax,word ptr [ExtendedAbsPos+00]
286; call AuxIO_TeletypeHexDWord
287; call AuxIO_TeletypeNL
288 pop dx
289
290 xor dh,dh
291 and dl,01111111b
292 shl dx,1
293 shl dx,1
294 mov bx, offset TrueSecs
295 add bx,dx
296
297 mov ax, word ptr[bx]
298; call AuxIO_TeletypeHexWord
299; call AuxIO_TeletypeNL
300 mov al,[ExtendedAbsPosSet] ; if true -> 1st sector of extpart (EBR), not logpart(BPB)
301; call AuxIO_TeletypeHexByte
302; call AuxIO_TeletypeNL
303 ; mov si,offset PartitionSector
304 ; call AuxIO_DumpSector
305 popa
306
307 ; LBA
308 mov si,offset before_lvm_adjust
309; call AuxIO_Print
310
311 xchg dx,bx
312; call AuxIO_TeletypeHexDWord
313; call AuxIO_TeletypeNL
314 xchg bx,dx
315 popa
316
317
318 ;or bx,ax
319 test [ExtendedAbsPosSet],1
320 jz pri
321
322
323
324
325 pusha
326 mov si,offset before_lvm_adjust_log
327; call AuxIO_Print
328 ; LBA
329 xchg dx,bx
330; call AuxIO_TeletypeHexDWord
331; call AuxIO_TeletypeNL
332 xchg bx,dx
333 popa
334
335
336 push dx
337 push bx
338 xor dh,dh
339 and dl,01111111b
340 shl dx,1
341 shl dx,1
342 mov bx,offset TrueSecs
343 add bx,dx
344 mov dx,[bx]
345 dec dx
346 add ax,dx
347 pop bx
348 pop dx
349 adc bx,0
350
351
352 pusha
353 mov si,offset after_lvm_adjust_log
354; call AuxIO_Print
355 ; LBA
356 xchg dx,bx
357; call AuxIO_TeletypeHexDWord
358; call AuxIO_TeletypeNL
359 xchg bx,dx
360 popa
361
362 jmp done
363
364
365
366
367pri:
368
369
370 push ax
371 push cx
372 xor ch, ch ; Zero out upper-byte
373
374 push dx
375 xor dh,dh
376 and dl,01111111b
377 shl dx,1
378 shl dx,1
379 push bx
380 mov bx,offset TrueSecs
381 add bx,dx
382 mov ax,[bx]
383 ;mov [ts2],ax
384 pop bx
385 pop dx
386
387
388
389 ;mov al, 63
390 ;call VideoIO_PrintByteDynamicNumber
391 ;self: jmp self
392
393
394
395 ; DEZE WERKT SOMS NIET GOED
396 ; ROMMELT MET CYLINDERS
397 ; ALLEEN TOEPASSEN ALS INT13X NIET ACTIEF !
398
399 and cl, al ; Isolate lower bits, because upper
400 mov ah, 0
401 mov si, ax ; ones may be used for cylinder
402 sub si, cx
403
404 pop cx
405 pop ax
406
407 or cl, al ; Set sector to last sector
408
409 add ax, si ; Adjust lower LBA
410 adc bx, 0 ; Adjust LBA Sector (BX:AX)
411
412
413
414 ;push ax
415 ;call AuxIO_TeletypeHexWord
416 ;call AuxIO_TeletypeNL
417 ;mov ax,[ts]
418 ;call AuxIO_TeletypeHexWord
419 ;call AuxIO_TeletypeNL
420 ;mov ax,[ts2]
421 ;call AuxIO_TeletypeHexWord
422 ;call AuxIO_TeletypeNL
423 ;pop ax
424
425 ;and ax,[ts]
426
427 jmp done
428
429
430
431done:
432
433
434
435 pusha
436 mov si,offset after_lvm_adjust
437; call AuxIO_Print
438 ; LBA
439 xchg dx,bx
440; call AuxIO_TeletypeHexDWord
441; call AuxIO_TeletypeNL
442 xchg bx,dx
443 popa
444
445
446
447; pusha
448; call AuxIO_TeletypeNL
449
450 ; CYL
451; mov al,ch
452; call AuxIO_TeletypeHexByte
453; call AuxIO_TeletypeNL
454
455 ; HEAD
456; mov al,dh
457; call AuxIO_TeletypeHexByte
458; call AuxIO_TeletypeNL
459
460 ; SEC
461; mov al,cl
462; call AuxIO_TeletypeHexByte
463; call AuxIO_TeletypeNL
464
465 ; DRIVE
466; mov al,dl
467; call AuxIO_TeletypeHexByte
468; call AuxIO_TeletypeNL
469
470; popa
471
472
473
474 ret
475DriveIO_LVMAdjustToInfoSector EndP
476
477drive db 'drive : ',0
478before_lvm_adjust db 'before lvm adjust : ',0
479after_lvm_adjust db 'after lvm adjust : ',0
480before_lvm_adjust_log db 'before lvm logical adjust: ',0
481after_lvm_adjust_log db 'after lvm logical adjust : ',0
482spt_used db 'spt used : ',0
483
484
485
486; #########################################################################
487; Routine: Loads partition to ExecBase and checks for validity
488; #########################################################################
489; Calling : bx:ax - Absolute sector
490; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
491; Returns : Carry Set if invalid partition encountered
492; Preserve: all registers
493; #########################################################################
494DriveIO_LoadPartition Proc Near Uses si
495 mov wptr cs:[CurPartition_Location+0], ax
496 mov wptr cs:[CurPartition_Location+2], bx
497 mov wptr cs:[CurPartition_Location+4], dx
498 mov wptr cs:[CurPartition_Location+6], cx ; Saves the location
499 mov si, offset PartitionSector ; DS:SI - ExecBase
500 call DriveIO_LoadSector
501 clc
502 cmp wptr [si+LocBR_Magic], 0AA55h
503 je DIOLP_Success
504 ; We check, if we are scanning partitions. In that case, if CHS is not 0/0/1
505 ; we will display a "bad partition table" message and halt the system.
506 cmp cx, 0001h
507 jne DIOLP_Failed
508 or dh, dh
509 jnz DIOLP_Failed
510 stc ; Set carry, so no partition table
511 DIOLP_Success:
512
513IFDEF AuxDebug
514 ; show current partition location
515 pushf
516 pusha
517 call AuxIO_TeletypeNL
518 mov si,offset db_curpartloc
519 call AuxIO_Print
520 mov dx,word ptr [CurPartition_Location+02]
521 mov ax,word ptr [CurPartition_Location+00]
522 call AuxIO_TeletypeHexDWord
523 call AuxIO_TeletypeNL
524 mov si,offset PartitionSector
525 call AuxIO_DumpSector
526 call AuxIO_TeletypeNL
527 popa
528 popf
529ENDIF
530
531 ret
532 DIOLP_Failed:
533 jmp DriveIO_GotLoadError
534DriveIO_LoadPartition EndP
535
536; #########################################################################
537; Routine: Writes a partition from ExecBase to its original sector
538; #########################################################################
539; Calling : none
540; Returns : none
541; Preserve: all registers
542; #########################################################################
543DriveIO_SavePartition Proc Near Uses ax bx cx dx si
544 mov ax, wptr cs:[CurPartition_Location+0]
545 mov bx, wptr cs:[CurPartition_Location+2]
546 mov dx, wptr cs:[CurPartition_Location+4]
547 mov cx, wptr cs:[CurPartition_Location+6] ; Gets prev. saved location
548 mov si, offset PartitionSector ; DS:SI - ExecBase
549 cmp wptr [si+LocBR_Magic], 0AA55h ; Checks for signature, if not found
550 jne DIOSP_SevereError ; we assume a really bad error
551 call DriveIO_SaveSector
552 DIOSP_SevereError:
553 ret
554DriveIO_SavePartition EndP
555
556; Keeps DS:SI for caller
557DriveIO_LoadTmpSector Proc Near
558 mov si, offset TmpSector
559 call DriveIO_LoadSector ; Uses INT13X if needed
560 ret
561DriveIO_LoadTmpSector EndP
562
563; Keeps DS:SI for caller
564DriveIO_SaveTmpSector Proc Near
565 mov si, offset TmpSector
566 call DriveIO_SaveSector
567 ret
568DriveIO_SaveTmpSector EndP
569
570; Keeps DS:SI for caller, sets carry if valid LVM sector encountered
571DriveIO_LoadLVMSector Proc Near Uses ax bx cx dx
572 test [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
573 jnz DIOLLVMS_NoLVMSector ; don't load but declare as bad!
574 mov ax, wptr cs:[CurPartition_Location+0]
575 mov bx, wptr cs:[CurPartition_Location+2]
576 mov dx, wptr cs:[CurPartition_Location+4]
577 mov cx, wptr cs:[CurPartition_Location+6] ; Gets cur. partition location
578
579 call DriveIO_LVMAdjustToInfoSector
580
581 mov si, offset LVMSector
582 call DriveIO_LoadSector
583
584IFDEF AuxDebug
585 ; show current partition location
586 pushf
587 pusha
588; call AuxIO_TeletypeNL
589 mov si,offset db_curlvmsec
590; call AuxIO_Print
591 mov dx,bx
592; call AuxIO_TeletypeHexDWord
593; call AuxIO_TeletypeNL
594 mov si,offset LVMSector
595; call AuxIO_DumpSector
596; call AuxIO_TeletypeNL
597 popa
598 popf
599ENDIF
600
601 call LVM_CheckSectorSignature
602 jnc DIOLLVMS_NoLVMSector
603 call LVM_CheckSectorCRC
604 jnc DIOLLVMS_NoLVMSector
605 ret
606 ; This here is called, if an invalid (or no) LVM information sector is found
607 ; It will truncate the first byte of the sector, so all other routines
608 ; will notice it easily by just comparing the first byte.
609 DIOLLVMS_NoLVMSector:
610 mov bptr [si+LocLVM_SignatureStart], 0
611 ret
612DriveIO_LoadLVMSector EndP
613
614; Keeps DS:SI for caller, saves at anytime w/o checks (!)
615DriveIO_SaveLVMSector Proc Near Uses ax bx cx dx
616 test [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
617 jnz DIOSLVMS_SevereError ; don't save at anytime (security!)
618 mov ax, wptr cs:[CurPartition_Location+0]
619 mov bx, wptr cs:[CurPartition_Location+2]
620 mov dx, wptr cs:[CurPartition_Location+4]
621 mov cx, wptr cs:[CurPartition_Location+6] ; Gets cur. partition location
622 call LVM_CheckSectorSignature
623 jnc DIOSLVMS_SevereError ; LVM Signature must be there
624 call DriveIO_LVMAdjustToInfoSector
625 mov si, offset LVMSector
626 call DriveIO_SaveSector
627 DIOSLVMS_SevereError:
628 ret
629DriveIO_SaveLVMSector EndP
630
631; Memory-Block that holds information for LBA-access via INT 13h
632DriveIO_DAP db 10h ; Size of paket
633 db 0 ; Reserved
634DriveIO_DAP_NumBlocks dw 0 ; Number of blocks
635DriveIO_DAP_Transfer dd 0 ; Transfer Adress
636DriveIO_DAP_Absolute dd 0 ; Absolute Sector
637 dd 0 ; Second Part of QWORD
638
639; Special error message instead of "LOAD ERROR" during partition scanning,
640; so users will notice that something is bad with their partition table(s)
641DriveIO_GotLoadError Proc Near
642 test cs:CurIO_Scanning, 1 ; Must be CS:, cause DS!=CS maybe here
643 jnz InScanMode
644 jmp MBR_LoadError
645 InScanMode:
646 mov si, offset TXT_BrokenPartitionTable
647 push cs
648 pop ds
649 call MBR_Teletype
650 mov si, offset BrokenHDD
651 sub dl, 50h ; 80h -> '0'
652 cmp dl, 39h
653 jbe DIOGLE_BelowA
654 add dl, 7 ; 3Ah -> 'A'
655 DIOGLE_BelowA:
656 mov bptr [si+5], dl
657 call MBR_Teletype
658
659 ; JWasm: cannot jump to local label in procedure.
660 ; Changed to halt here.
661 ;jmp MBRLE_Halt
662 DriveIO_GotLoadError_halt:
663 jmp DriveIO_GotLoadError_halt
664DriveIO_GotLoadError EndP
665
666; #########################################################################
667; Routine: Loads a specified sector to DS:DI
668; #########################################################################
669; Calling : bx:ax - Absolute sector
670; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
671; ds:si - Destination-Adress
672; Returns : none
673; Preserve: all registers
674; #########################################################################
675DriveIO_LoadSector Proc Near Uses ax bx ds si es di
676 ; Is the drive not a harddrive?
677 cmp dl, 80h
678 jb DIOLS_UseNormal
679
680 test cs:[CurIO_UseExtension], 1
681 jz DIOLS_UseNormal
682 ; Are we forced do use LBA via Setting?
683 jnz DIOLS_UseExtension
684
685 ; Upper 8 bits of LBA-address set? -> Use LBA (maximum boundary is FB0400h)
686 or bh, bh
687 jnz DIOLS_UseExtension
688 ; Compare Switch-Table value to bit 16-23 of LBA-address
689 mov di, dx
690 and di, 007Fh
691 cmp bptr cs:[LBASwitchTable+di], bl
692 jbe DIOLS_UseExtension
693 DIOLS_UseNormal:
694 mov di, 3
695 DIOLS_ErrorLoop:
696 push ds
697 pop es
698 mov bx, si ; ES:BX - Destination
699 mov ax, 0201h ; Function 2 - Load Sector
700 int 13h
701 jnc DIOLS_Success
702 dec di
703 jnz DIOLS_ErrorLoop
704 ; Sector load failed...
705 jmp DriveIO_GotLoadError
706
707 DIOLS_UseExtension:
708 push cx
709 mov cs:[DriveIO_DAP_NumBlocks], 1 ; Copy ONE sector
710 mov wptr cs:[DriveIO_DAP_Transfer+0], si
711 mov cx, ds
712 mov wptr cs:[DriveIO_DAP_Transfer+2], cx ; Fill out Transfer Adress
713 mov wptr cs:[DriveIO_DAP_Absolute+0], ax
714 mov wptr cs:[DriveIO_DAP_Absolute+2], bx ; Fill out Absolute Sector
715 push cs
716 pop ds
717 mov si, offset DriveIO_DAP
718 mov ah, 42h ; Extended Read
719 int 13h
720 pop cx
721 jnc DIOLS_Success
722 ; Sector load failed...
723 jmp DriveIO_GotLoadError
724
725 DIOLS_Success:
726 ret
727DriveIO_LoadSector EndP
728
729
730
731;
732; ############################################################
733; # Load a specified sector from a disk using LBA addressing #
734; ############################################################
735;
736; In
737; --
738; DL = Physical Disk
739; BX:CX = LBA sector
740; DI:SI = Target buffer
741;
742; Out
743; ---
744; AX = Error code
745;
746DriveIO_LoadSectorLBA Proc Near Uses bx cx dx si di ds es
747 ; Get one sector
748 mov cs:[DriveIO_DAP_NumBlocks], 1
749
750 ; Setup buffer address
751 mov wptr cs:[DriveIO_DAP_Transfer+0], si
752 mov wptr cs:[DriveIO_DAP_Transfer+2], di
753
754 ; Setup LBA address of requested sector
755 mov wptr cs:[DriveIO_DAP_Absolute+0], cx
756 mov wptr cs:[DriveIO_DAP_Absolute+2], bx
757 mov wptr cs:[DriveIO_DAP_Absolute+4], 0
758 mov wptr cs:[DriveIO_DAP_Absolute+6], 0
759
760 ; Address of packet
761 mov si, offset DriveIO_DAP
762
763 ; Do the extended read
764 mov ah, 42h
765 int 13h
766
767 ; Looking good so far
768 jnc DriveIO_LoadSectorLBA_succes1
769
770 ; AH should not be zero, if it is then set to undefined and set carry
771 test ah,ah
772 jnz DriveIO_LoadSectorLBA_error1
773 mov ah, 0bbh ; Undefined error
774 DriveIO_LoadSectorLBA_error1:
775 stc
776 jmp DriveIO_LoadSectorLBA_exit
777
778 ; AL should be zero, if not then set to undefined and set carry
779 DriveIO_LoadSectorLBA_succes1:
780 test ah,ah
781 jz DriveIO_LoadSectorLBA_exit
782 stc
783 jmp DriveIO_LoadSectorLBA_exit
784
785 ; Return to caller
786 DriveIO_LoadSectorLBA_exit:
787 ret
788DriveIO_LoadSectorLBA EndP
789
790
791
792
793; #########################################################################
794; Routine: Writes DS:SI to a specified sector
795; #########################################################################
796; Calling : bx:ax - Absolute sector
797; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
798; ds:si - Source-Adress
799; Returns : none
800; Preserve: all registers
801; #########################################################################
802DriveIO_SaveSector Proc Near Uses ax bx cx ds si es di
803 test cs:[CurIO_UseExtension], 1
804 jz DIOSS_UseNormal
805 ; Are we forced do use LBA via Setting?
806 test cs:[CFG_ForceLBAUsage], 1
807 jnz DIOSS_UseExtension
808 ; Is the drive not a harddrive?
809 cmp dl, 80h
810 jb DIOSS_UseNormal
811 ; Upper 8 bits of LBA-address set? -> Use LBA (maximum boundary is FB0400h)
812 or bh, bh
813 jnz DIOSS_UseExtension
814 ; Compare Switch-Table value to bit 16-23 of LBA-address
815 mov di, dx
816 and di, 007Fh
817 cmp bptr cs:[LBASwitchTable+di], bl
818 jbe DIOSS_UseExtension
819 DIOSS_UseNormal:
820 mov di, 3
821 DIOSS_ErrorLoop:
822 push ds
823 pop es
824 mov bx, si ; ES:BX - Destination
825 mov ax, 0301h ; Function 3 - Write Sector
826 int 13h
827 jnc DIOSS_Success
828 dec di
829 jnz DIOSS_ErrorLoop
830 call MBR_SaveError
831
832 DIOSS_UseExtension:
833 push cx
834 mov cs:[DriveIO_DAP_NumBlocks], 1 ; Copy ONE sector
835 mov wptr cs:[DriveIO_DAP_Transfer+0], si
836 mov cx, ds
837 mov wptr cs:[DriveIO_DAP_Transfer+2], cx ; Fill out Transfer Adress
838 mov wptr cs:[DriveIO_DAP_Absolute+0], ax
839 mov wptr cs:[DriveIO_DAP_Absolute+2], bx ; Fill out Absolute Sector
840 push cs
841 pop ds
842 mov si, offset DriveIO_DAP
843 mov ax, 4300h ; Extended Write (No Verify)
844 int 13h
845 pop cx
846 jnc DIOSS_Success
847 call MBR_SaveError
848
849 DIOSS_Success:
850 ret
851DriveIO_SaveSector EndP
852
853
854; See if a LVM-sector is valid.
855; In : si, pointer to sector
856; Out : CY if valid LVM sector, NC if not
857DriveIO_LVMSectorValid Proc Near
858 pusha
859
860 call LVM_CheckSectorSignature
861 ; NC if no signature found
862 jnc DriveIO_LVMSectorValid_End
863
864 call LVM_CheckSectorCRC
865 ; Force valid !!!
866 stc
867
868 DriveIO_LVMSectorValid_End:
869 popa
870 ret
871DriveIO_LVMSectorValid EndP
872
873; ------------------------------------------------------
874; Rousseau: # Load the master LVM-sector if one exists #
875; ------------------------------------------------------
876; Load the master LVM-sector to get the number of sectors per track as eCS views the drive.
877; If no master LVM-sector is found it is assumed eCS is not installed.
878; The master LVM-sector can be located at three different places according to drive size
879; and partitioning scheme and driver used.
880; When DANIS506.ADD is used, the eCS extended geometry will be 255/127 for drives >502GiB but <1TiB.
881; Then the location will be sector 127 which is LBA 126 (7Eh).
882; IBM1S506.ADD will always use 255/255 for the extended eCS geometry.
883; DANIS506.ADD will use 255/255 for drives >1TiB.
884; Then the location of the master LVM-sector will be 255 which is LBA 254 (FEh).
885; When eCS is installed on a huge drive that alread had a system on it, eCS will be confined to the
886; lower 502GiB of the drive. In this case the normal geometry from Int13X will be used.
887; This is also the case when no valid master LVM-sector can be found.
888;
889; Return CF when valid master LVM sector found, NC if not.
890; Loads sector at [LVMSector] !
891DriveIO_LoadMasterLVMSector Proc Near
892 pusha
893
894 ;mov si,offset db_lmlvm
895 ;call AuxIO_Print
896
897 ; Physical disk
898; mov al,'<'
899; call VideoIO_PrintSingleChar
900; mov al,dl
901; call VideoIO_PrintHexByte
902; mov al,'>'
903; call VideoIO_PrintSingleChar
904
905 ;call AuxIO_TeletypeHexByte
906 ;call AuxIO_TeletypeNL
907
908
909 ; Loop over the sector-translation table,
910 ; process the first three values from high (255) to low (bios spt, most likely 63)
911 mov cx,3
912 DriveIO_LoadMasterLVMSector_NextTry:
913 ; Number of sectors to read
914 mov [DriveIO_DAP_NumBlocks],1
915
916 ; Setup destination address
917 mov si, offset LVMSector
918 mov wptr [DriveIO_DAP_Transfer+0],si
919 mov ax, ds
920 mov wptr [DriveIO_DAP_Transfer+2],ax
921
922 ; Get the sector-number of the next possible LVM sector (255,127,63)
923 ; using the translation table and the counter as the index
924 mov bx,offset secs_per_track_table
925 mov ax,cx
926 dec ax
927 xlatb
928 dec al
929
930 ;
931 ; AX now contains the LBA address of the sector
932 ; that could be an LVM sector.
933 ; This is all in track0 so the address will not exceed 64kiB sectors.
934 ;
935
936; push ax
937; push ax
938; mov al,'$'
939; call VideoIO_PrintSingleChar
940; pop ax
941; call VideoIO_PrintHexByte
942; mov al,'$'
943; call VideoIO_PrintSingleChar
944; pop ax
945
946IFDEF AuxDebug
947 ; Dump the value
948 ;call AuxIO_TeletypeHexByte
949 ;call AuxIO_TeletypeNL
950ENDIF
951
952 ; Setup the requested LBA sector number
953 mov wptr [DriveIO_DAP_Absolute+0],ax ; LBA low
954 mov wptr [DriveIO_DAP_Absolute+2],00h ; LBA high
955 mov si, offset DriveIO_DAP ; address request packet
956 mov ah, 42h
957 int 13h ; do the i/o
958 cmc ; Complement carry so we can exit imm. on error
959 jnc DriveIO_LoadMasterLVMSector_End ; oops, return with NC
960
961
962 mov si,offset LVMSector
963
964 ; See if this is a valid LVM-sector
965 call DriveIO_LVMSectorValid
966
967; pushf
968; mov ah,0
969; rcl ah,1
970; mov al,'|'
971; call VideoIO_PrintSingleChar
972; mov al,ah
973; call VideoIO_PrintHexByte
974; mov al,'|'
975; call VideoIO_PrintSingleChar
976; popf
977
978
979 ; Yep, we found the master LVM-sector
980 jc DriveIO_LoadMasterLVMSector_Found
981 ; Try next location
982 loop DriveIO_LoadMasterLVMSector_NextTry
983
984 ; No master LVM-sector found, set CF=false
985 clc
986
987 DriveIO_LoadMasterLVMSector_Found:
988 DriveIO_LoadMasterLVMSector_End:
989 popa
990 ret
991DriveIO_LoadMasterLVMSector Endp
992
993
994
995
996; ---------------------------------------------------
997; Rousseau ## Large drives, (eCS) geometry and LBA ##
998; ---------------------------------------------------
999; A sector size of 512 bytes is assumed in the below calculations.
1000; Note that this scheme changes when the sector size will be 4096 or larger,
1001; like with modern drives that do not translate to 512 bytes per sector anymore.
1002; These drives will have a capacity above the 2TiB LBA32 boundary.
1003; For now, we assume drives <=2TiB with a sector size of 512 bytes.
1004
1005; There are a few boundaries that are of importance.
1006; Note that these are disk-boundaries and not partition boundaries.
1007; Even with a small partition, like <502GiB, OS/2 will use extended geometry on an
1008; empty huge disk.
1009; These boundaries are (from high to low):
1010
1011; (code 5)
1012; 2^32 = 4294967296 = 100000000 sectors = 2048 GiB
1013; This is the LBA32 2TiB boundary.
1014; Everything above it must be addressed using LBA48.
1015; OS/2 can currently not address this space above.
1016
1017; (code4)
1018; 65536*255*255 = 4261478400 = FE010000 sectors ~ 2032 GiB
1019; This is the max OS/2 boundary using 255/255 extended geometry.
1020; OS/2 can currently not address this space above.
1021
1022; (code 3)
1023; 2^31 = 2147483648 = 80000000 sectors = 1024 GiB
1024; This is the LBA32 1TiB boundary.
1025; OS/2 can address this space and will use 255/255 extended geometry.
1026
1027; (code 2)
1028; 65536*255*127 = 2122383360 = 7E810000 sectors ~ 1012 GiB
1029; This is the DANI 1TiB boundary.
1030; OS/2 can address this space and will use 255/255 extended geometry.
1031; Below this DANI will use 255/127 extended geometry.
1032; This matters on where the LVM-sectors are located !
1033
1034; (code 1)
1035; 65536*255*63 = 1052835840 = 3EC10000 sectors ~ 502 GiB
1036; This is the current OS/2 limit using this geometry because OS/2 can currently
1037; not address more than 65536 cylinders.
1038; DANI will address space above with 255/127 extended geometry up until the DANI 1TiB boundary (code 2)
1039
1040; (code 0)
1041; Everything below 65536*255*63 will be addressed using standard geometry.
1042
1043
1044;
1045; This function will return the following values:
1046;
1047
1048; 5 = This drive is above the 2^32 LBA32 (2TB) boundary and has more than 4294967296 sectors.
1049; LBA48 addressing is needed to access the complete capacity of the drive.
1050; OS/2 is currently unable to do so.
1051
1052; 4 = This drive is above the 65536*255*255 (4261478400) boundary but below 2^32.
1053; This is an OS/2 boundary and OS/2 is not able to access the drive above this boundary.
1054
1055; 3 = This drive is above the 2^31 (1TB) boundary and has more than 2147483648 sectors.
1056; OS/2 is able to access the drive using it's extended geometry.
1057; Both DANIS506 and IBM1S506 will use the 255/255 scheme.
1058
1059; 2 = This drive is above the 65536*255*127 (2122383360) boundary but below 2^31.
1060; OS/2 is able to access the drive using it's extended geometry.
1061; Both DANIS506 and IBM1S506 will use the 255/255 scheme.
1062
1063; 1 = This drive is above the 65536*255*63 (1052835840) boundary but below 65536*255*127.
1064; OS/2 is able to access the drive using it's extended geometry.
1065; Note that DANIS506 will use 255/127 and IBM1S506 will use 255/255 geometry !
1066; Using DANI or IBM influences the location of the LVM info-sectors !
1067
1068; 0 = This drive is below the 65536*255*63 (1052835840) boundary.
1069; OS/2 is able to access this drive using the standard 255/63 geometry.
1070
1071; So, any return value >0 means OS/2 extended geometry will be used.
1072; Value 1 will use 255/127 with DANIS506 but 255/255 with IBM1S506.
1073; Values 2 and 3 will use 255/255 on both drivers.
1074; You can or with 0x01 and check for 3 in this case.
1075; Any value above 3 will be a drive who's capacity cannot be fully used by OS/2
1076; The upper limit of 65536*255*255 will be in effect here.
1077
1078; Note this function currently handles the boot-drive only !
1079; It should be extended and use dl for the drive-number as a parameter.
1080; Because we use this function to get this info in a number of places,
1081; all regs and flags except AX are saved and restored.
1082
1083; DL contains BIOS disk-number; 80h for first, 81h for second, etc.
1084DriveIO_GatherDiskInfo Proc Near
1085 pushf
1086 push bx
1087 push cx
1088 push dx
1089 push si
1090 push di
1091 push es
1092
1093 ; Set ES to CS for buffer clearing
1094 push cs
1095 pop es
1096
1097 ; Clear the buffer
1098 ; Don't overwrite the word of the buffersize at index 0 !
1099 ; Old Phoenix BIOSses require word (flags) at 02 to be zero,
1100 ; so we clear the whole buffer to be sure.
1101 mov cx, i13xbuf_size
1102 mov di, offset i13xbuf
1103 mov [di],cx
1104 inc di
1105 inc di
1106 xor ah,ah
1107 cld
1108 rep stosb
1109
1110 ; Get the drive parameters
1111 mov ah, 48h ; Get Drive Parameters (extended version)
1112 ;mov dl, 80h ; Drive number
1113 mov si, offset i13xbuf ; Buffer for result-info
1114 push dx
1115 int 13h ; Call the BIOS-function
1116 pop dx
1117
1118 ; Do some error-checking
1119 or ah,ah ; AH is zero if no error (ZF=1 if no error)
1120 mov ax,0 ; Setup code for non-huge drive (does not influence ZF)
1121 jz DriveIO_GatherDiskInfo_ok ; Return if error (AL<>0 thus ZF=0) but CY not set, assuming non-huge drive
1122 jnc DriveIO_GatherDiskInfo_ok ; Return if error (CY=1), assuming non-huge drive
1123 jmp DriveIO_GatherDiskInfo_ret
1124
1125
1126 DriveIO_GatherDiskInfo_ok:
1127
1128 ;
1129 ; Store the drive geometry
1130 ;
1131
1132 mov si, offset i13xbuf
1133
1134 xor dh,dh
1135 and dl,01111111b
1136 shl dx,1
1137 shl dx,1
1138
1139 ; Store number of cylinders on disk
1140 mov bx, offset BIOS_Cyls
1141 add bx,dx
1142 mov ax,[si+04h]
1143
1144 mov word ptr [bx+00],ax
1145 mov ax,[si+06]
1146 mov word ptr [bx+02],ax
1147
1148 ; Store number of heads per cylinder
1149 mov bx, offset BIOS_Heads
1150 add bx,dx
1151 mov ax,[si+08h]
1152 mov word ptr [bx+00],ax
1153 mov ax,[si+0ah]
1154 mov word ptr [bx+02],ax
1155
1156 ; Store number of sectors per track
1157 mov bx, offset BIOS_Secs
1158 add bx,dx
1159 mov ax,[si+0ch]
1160 mov word ptr [bx+00],ax
1161
1162 ; Update first byte of translation-table to conform to BIOS SPT
1163 mov byte ptr [secs_per_track_table], al
1164
1165 mov ax,[si+0eh]
1166 mov word ptr [bx+02],ax
1167
1168 ; Store total secs
1169 mov bx, offset BIOS_TotalSecs
1170 add bx,dx
1171 add bx,dx
1172 mov ax,[si+10h]
1173
1174 mov word ptr [bx+00],ax
1175 mov ax,[si+12h]
1176 mov word ptr [bx+02],ax
1177 mov ax,[si+14h]
1178 mov word ptr [bx+04],ax
1179 mov ax,[si+18h]
1180 mov word ptr [bx+06],ax
1181
1182 ; Store number of bytes per sector
1183 mov bx, offset BIOS_Bytes
1184 add bx,dx
1185 mov ax,[si+18h]
1186 mov [bx],ax
1187
1188
1189 ;
1190 ; See of it's a huge drive of not
1191 ;
1192
1193 ; Drive is larger than 2TiB
1194 mov ax,5 ; Drive code (5)
1195 mov bx, [si+14h] ; Low word of high dword of sector-count
1196 or bx, [si+16h] ; High word of high dword of sector-count
1197 jnz DriveIO_GatherDiskInfo_ret ; If non-zero we have a drive with >2^32 sectors and thus LBA48 addressing
1198
1199 ; Drive is larger than max OS/2 capacity
1200 dec ax ; Drive code (4)
1201 mov bx, [si+12h] ; High word of low dword of sector-count
1202 cmp bx, 0fe01h ; Boundary
1203 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1204 ; we have a drive larger than to 65536*255*255 = FE010000 sectors
1205
1206 ; Drive can be completely utilized by OS/2
1207 dec ax ; Drive code (3)
1208 cmp bx, 8000h ; Boundary
1209 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1210 ; we have a drive larger than 2^31 sectors but smaller than 65536*255*255
1211
1212 ; This is the small area between DANI 1TiB and LBA 1TiB
1213 dec ax ; Drive code (2)
1214 cmp bx, 7e81h ; Boundary
1215 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1216 ; we have a drive larger than 65536*255*127 but <65536*255*255
1217 ; DANIS506.ADD will use 255/255 extended geometry
1218
1219 ; DANI will use 255/127 in this area, this could impact the location of LVM-sectors ! (last sec on track)
1220 dec ax ; Drive code (1)
1221 cmp bx, 3ec1h ; Boundary
1222 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1223 ; we have a drive larger than 65536*255*63 sectors (OS/2 502GiB Limit!)
1224 ; DANIS506.ADD will use 255/127 extended geometry !
1225 ; IBM1S506.ADD will use 255/255 extended geometry !
1226
1227 ; We have a drive that can be addressed using standard 255/63 geometry
1228 dec ax ; Drive code (0)
1229 ; We have a drive smaller than 65536*255*63 = 3EC10000 sectors
1230
1231 DriveIO_GatherDiskInfo_ret:
1232 pop es
1233 pop di
1234 pop si
1235 pop dx
1236 pop cx
1237 pop bx
1238
1239 mov [CurIO_UseExtension],1
1240
1241 popf
1242 ret
1243DriveIO_GatherDiskInfo EndP
1244
1245
1246
1247; Values for sectors per track table corresponding to DriveIO_IsHugeDrive return value.
1248secs_per_track_table db 63,127,255,255,255,255
1249
1250;db_lmlvm: db 'Load Master LVM -- disk: ',0
Note: See TracBrowser for help on using the repository browser.