source: trunk/bootcode/regular/driveio.asm@ 150

Last change on this file since 150 was 150, checked in by Ben Rietbroek, 8 years ago

Reimplemented the saving of LVM sectors [v1.1.1-testing]

This new method does away with ugly and faulty adjustments which
assumed LVM sectors were located below actual partition starts,
which is true most of the time, but not always, especially not for
the first primary partition which could be offset more than SPT.

Because MBR and EBR locations are now used, the need to distinguish
between primary and logical partitions is also not needed anymore.

CAUTION:
This is a testbuild !
AirBoot uses the BIOS to access disks and a small coding error can trash
partition tables or other vital disk structures. You are advised to make
backups of TRACK0 and EBRs before using this testbuild. More info at:
https://rousseaux.github.io/netlabs.air-boot/pdf/AirBoot-v1.1.0-manual.pdf

File size: 71.5 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 MODULE_NAMES
25DB 'DRIVEIO',0
26ENDIF
27
28;
29; Check if INT13X extensions are supported.
30; AirBoot requires these extensions, and will halt if they are not available.
31; Modified: [CurIO_UseExtension]
32DriveIO_CheckFor13extensions Proc Near Uses ax bx cx dx
33 mov ah, 41h
34 mov bx, 55AAh
35 mov dl, [BIOS_BootDisk] ; We check using the boot-disk
36 int 13h
37
38IFDEF AUX_DEBUG
39 IF 0
40 DBG_TEXT_OUT_AUX 'DriveIO_CheckFor13extensions:'
41 PUSHRF
42 call DEBUG_DumpRegisters
43 ;~ call AuxIO_DumpParagraph
44 ;~ call AuxIO_TeletypeNL
45 mov si, offset [Scratch]
46 mov word ptr [si], 50h
47 mov ah, 48h
48 int 13h
49 call DEBUG_DumpRegisters
50 ;~ call AuxIO_DumpSector
51 POPRF
52 ENDIF
53ENDIF
54
55 jc PCCF13E_NotFound ; Error occured
56 cmp bx, 0AA55h
57 je PCCF13E_Found
58 PCCF13E_NotFound:
59 ret
60 PCCF13E_Found:
61 and cx, 1 ; Check 42h-44h,47h,48h supported
62 jz PCCF13E_NotFound ; Sig OK but no support, strange beast
63 mov byte ptr [CurIO_UseExtension], 1
64 ret
65DriveIO_CheckFor13extensions EndP
66
67
68; Note: Some routines set DS/ES to CS or even address via CS, even if its not
69; needed. This was done for SECURITY. So DO NOT remove it.
70; Its there to make sure the correct data is loaded/written to/from
71; harddrive.
72;
73; IF YOU MODIFY ANYTHING IN HERE, YOU MAY EASILY BREAK YOUR HARDDRIVE!
74
75; Will only load base-configuration, will NOT load IPT nor Hide-Config
76; Those are originally loaded on startup and will NOT get reloaded.
77DriveIO_LoadConfiguration Proc Near Uses ax bx cx dx es
78
79IFDEF AUX_DEBUG
80 IF 0
81 DBG_TEXT_OUT_AUX 'DriveIO_LoadConfiguration:'
82 PUSHRF
83 ;~ call DEBUG_DumpRegisters
84 ;~ call AuxIO_DumpParagraph
85 ;~ call AuxIO_TeletypeNL
86 POPRF
87 ENDIF
88ENDIF
89
90;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
91 mov ax, cs
92 mov es, ax
93 mov bx, offset Configuration
94 xor dh, dh
95 mov dl, [BIOS_BootDisk] ; Disk we booted from
96 mov cx, 0037h ; Sector 55 (CHS)
97 mov ax, 0201h ; Function 02, read 1 sector...
98 int 13h
99 jnc DIOLC_NoError
100 call MBR_LoadError ; Will Abort BootUp
101
102
103 DIOLC_NoError:
104 ret
105DriveIO_LoadConfiguration EndP
106
107DriveIO_SaveConfiguration Proc Near Uses ax bx cx dx ds es si
108
109IFDEF AUX_DEBUG
110 IF 0
111 DBG_TEXT_OUT_AUX 'DriveIO_SaveConfiguration:'
112 PUSHRF
113 ;~ call DEBUG_DumpRegisters
114 ;~ call AuxIO_DumpParagraph
115 ;~ call AuxIO_TeletypeNL
116 POPRF
117 ENDIF
118ENDIF
119
120 mov ax, cs
121 mov ds, ax
122 mov es, ax ; Safety first (CS==DS==ES)
123 ; --- Overwrite Floppy-Name with "FloppyDrive"
124 mov si, offset TXT_Floppy_Drive
125 mov di, offset PartitionTable
126 sub di, 30 ; Adjust to Floppy-Name
127 mov cx, 11
128 rep movsb
129 mov si, offset Configuration ; Calculate new checksum
130 xor bx, bx
131
132 ; Changed from 5 to calculated value (not here, see compat. issue below)
133 ; Fixes issue: #2987 -- "air-boot doesn't remember drive letter"
134 ; Size of the ab-configuration in 512 byte sectors
135 ;mov cx, (MBR_BackUpMBR - Configuration) / 200h
136
137 ; AB v1.07 stores a 5 sector configuration with a 5 sector checksum.
138 ; AB v1.0.8+ *should* stores a 7 sector configuration with a
139 ; 7 sector checksum.
140 ; Because 5 was hardcoded here, SET(A)BOOT v1.07 will see see an AB v1.0.8+
141 ; config as corrupted, while this is not the case.
142 ; So, for compatibility reasons, in v1.0.8+, the checksum stored is over
143 ; 5 sectors, to be compatible with v1.07.
144 ; This may change (be corrected) in future versions !
145 mov cx,5
146
147 mov dx, [CFG_CheckConfig]
148 mov [CFG_CheckConfig], bx
149 DIOSC_Loop:
150 call MBR_GetCheckOfSector
151 loop DIOSC_Loop
152 mov [CFG_CheckConfig], bx
153 ; --------------------------------------------------------------------
154 ; ES == CS
155 mov bx, offset Configuration
156 xor dh, dh
157 mov dl, [BIOS_BootDisk] ; Disk we booted from
158 mov cx, 0037h ; Sector 55 (CHS)
159
160 ; Changed from 5 to calculated value
161 ; Fixes issue: #2987 -- "air-boot doesn't remember drive letter"
162 ; Size of the ab-configuration in 512 byte sectors
163 mov al, (MBR_BackUpMBR - Configuration) / 200h
164 mov ah,03h
165;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
166 int 13h
167 jnc DIOSC_NoError
168 call MBR_SaveError ; Will Abort BootUp
169 DIOSC_NoError:
170 ret
171DriveIO_SaveConfiguration EndP
172
173DriveIO_UpdateFloppyName Proc Near Uses bx cx dx ds si es di
174 mov ax, cs
175 mov ds, ax
176 mov es, ax
177
178 mov ah, 00h ; Function 0 - Reset Drive
179 xor dl, dl
180 int 13h
181 xor dx, dx ; Cylinder=0, Head=0
182 mov cx, 1 ; Sector=1, Drive=0
183 mov bx, offset TmpSector ; ES:BX - TmpSector
184 mov ax, 0201h ; Function 2 - Load Sector
185 int 13h
186 jnc DIOUFN_AllFine
187
188 ; --- Overwrite Floppy-Name with "No Disc"
189 mov si, offset TXT_Floppy_NoDisc
190 xor ax, ax
191 DIOUFN_WriteFloppyName:
192 mov di, offset PartitionTable
193 sub di, 30 ; Adjust to Floppy-Name
194 mov cl, 11
195 rep movsb
196 ret ; AX=-1 -> GotDisc, =0 -> NoDisc
197
198 ; --- Floppy found and read, data in TempSector
199 DIOUFN_AllFine:
200 mov ax, -1
201 mov si, offset TXT_Floppy_NoName
202 cmp wptr es:[bx+54], 'AF'
203 jne DIOUFN_WriteFloppyName
204 cmp wptr es:[bx+56], '1T'
205 jne DIOUFN_WriteFloppyName
206 cmp bptr es:[bx+58], '2'
207 jne DIOUFN_WriteFloppyName
208 mov si, bx
209 add si, 43 ; FAT12 - Volume Label Location
210 jmp DIOUFN_WriteFloppyName
211DriveIO_UpdateFloppyName EndP
212
213; =============================================================================
214; HARDDRIVE / GENERAL ACCESS
215; =============================================================================
216; The following routines are used for harddisc/floppy access.
217; The access is done via INT 13h/CHS or INT 13h/LBA.
218; Access will be done prefered by INT 13h/CHS, because it's (I wonder!) much
219; faster, than the LBA-method. I don't know, why LBA is so slow. Perhaps BIOS.
220;
221; Internal access (to AiR-BOOT) is always done via INT 13h/CHS.
222
223DriveIO_GetHardDriveCount Proc Near Uses ds si
224 push ds
225 push si
226 push 0040h
227 pop ds
228 mov si, 0075h
229 mov dh, ds:[si] ; 40:75 -> POST: Total Harddiscs == DL
230 pop si
231 pop ds
232 mov [TotalHarddiscs], dh
233 ret
234DriveIO_GetHardDriveCount EndP
235
236
237; Fills our LBA-Usage table. It holds the LBA-address, where BIOS/CHS access is
238; stopped and BIOS/LBA access is started.
239; This is calculated by Sector*Heads. Comparing will get done with Bit 25-10
240; on LBA sectors, so we actually divide sector number by 1024.
241DriveIO_InitLBASwitchTable Proc Near Uses es di
242 mov di, offset LBASwitchTable
243 mov dh, [TotalHarddiscs]
244 mov dl, 80h ; First disk to process
245 DIOILUT_DriveLoop:
246 push dx
247 push di
248 mov ah, 08h
249 int 13h ; DISK - GET DRIVE PARAMETERS
250 mov ah, 0FBh ; Assume 255 heads/63 sectors, if error
251 jc DIOILUT_Error
252 and cl, 111111b ; Isolate lower 6 bits of CL -> sector count
253;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
254 ;movzx ax, cl
255 mov al,cl
256 mov ah,0
257
258 mov bl, dh ; DH -> max head number
259 mul bl ; AX = Sectors*Heads
260 shl ah, 1
261 shl ah, 1 ; Shift 2 bits, so we are able to compare to
262 ; bit 16-23 of the LBA address
263 DIOILUT_Error:
264 pop di
265 pop dx
266 mov bptr ds:[di], ah ; Save that value
267 inc di ; Go to next BYTE
268 inc dl ; Next disk
269 dec dh ; Decrease disks to process
270 jnz DIOILUT_DriveLoop ; Next disk if DH != 0
271 ret
272DriveIO_InitLBASwitchTable EndP
273
274
275
276
277;FIXME: Only LBA gets updated, need to update CHS too !!!!!!!
278
279; Adjusts BX:AX / CX:DX to meet LVM sector location
280; BX:AX / CX:DX point to MBR or EBR !
281; Destroys SI
282; Rousseau: Enhanced to handle sector-numbers 127 and 255 besides 63 for LVM-info sectors.
283; Ugly, need to cleanup.
284DriveIO_LVMAdjustToInfoSector Proc Near
285
286IFDEF AUX_DEBUG
287 IF 0
288 DBG_TEXT_OUT_AUX 'DriveIO_LVMAdjustToInfoSector:'
289 PUSHRF
290 call DEBUG_DumpRegisters
291 ;~ call AuxIO_DumpParagraph
292 ;~ call AuxIO_TeletypeNL
293 POPRF
294 ENDIF
295ENDIF
296
297 push cx ; Save Cyl/Sec part
298 xor ch,ch ; Clear low Cyl part
299 and cl,63 ; Clear high Cyl part
300 push bx ; We need BX...
301 push dx ; and DX temoraily
302 mov bx,offset [TrueSecs] ; Offset of sector table
303 xor dh,dh ; Clear DH because we use DL as index
304 and dl,01111111b ; Remove high bit of BIOS disk-nr
305 shl dx,2 ; Index to DWORD table
306 add bx,dx ; Point to TrueSecs for this disk
307 mov si,[bx] ; Get SPT for this disk
308 pop dx ; Restore DX...
309 pop bx ; and BX
310 ;~ sub si,cx ; Adjust offset !! INCORRECT FOR LBA (TP CX != 0 !!)
311 dec si
312 pop cx ; Restore Cyl/Sec part
313 add ax,si ; Add offset to low part...
314 adc bx,0 ; and high part of LBA address
315 or cl,63 ; Adjust CHS part !FIX ME for > 63! !! FIX HUGE DRIVE !!
316
317IFDEF AUX_DEBUG
318 IF 0
319 DBG_TEXT_OUT_AUX 'adjusted'
320 PUSHRF
321 call DEBUG_DumpRegisters
322 ;~ call AuxIO_DumpParagraph
323 ;~ call AuxIO_TeletypeNL
324 POPRF
325 ENDIF
326ENDIF
327
328 ret
329
330DriveIO_LVMAdjustToInfoSector EndP
331
332
333
334
335
336
337; #########################################################################
338; Routine: Loads partition to ExecBase and checks for validity
339; #########################################################################
340; Calling : bx:ax - Absolute sector
341; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
342; Returns : Carry Set if invalid partition encountered
343; Preserve: all registers
344; #########################################################################
345DriveIO_LoadPartition Proc Near Uses si
346
347IFDEF AUX_DEBUG
348 IF 0
349 DBG_TEXT_OUT_AUX 'DriveIO_LoadPartition:'
350 PUSHRF
351 call DEBUG_DumpRegisters
352 ;~ call AuxIO_DumpParagraph
353 ;~ call AuxIO_TeletypeNL
354 POPRF
355 ENDIF
356ENDIF
357
358 mov wptr cs:[CurPartition_Location+0], ax
359 mov wptr cs:[CurPartition_Location+2], bx
360 mov wptr cs:[CurPartition_Location+4], dx
361 mov wptr cs:[CurPartition_Location+6], cx ; Saves the location
362 mov si, offset PartitionSector ; DS:SI - ExecBase
363
364
365;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
366 call DriveIO_LoadSector
367
368 clc
369 cmp wptr [si+LocBR_Magic], 0AA55h
370 je DIOLP_Success
371 ; We check, if we are scanning partitions. In that case, if CHS is not 0/0/1
372 ; we will display a "bad partition table" message and halt the system.
373 cmp cx, 0001h
374 jne DIOLP_Failed
375 or dh, dh
376 jnz DIOLP_Failed
377 stc ; Set carry, so no partition table
378 DIOLP_Success:
379
380
381
382 ret
383 DIOLP_Failed:
384 jmp DriveIO_GotLoadError
385DriveIO_LoadPartition EndP
386
387; #########################################################################
388; Routine: Writes a partition from ExecBase to its original sector
389; #########################################################################
390; Calling : none
391; Returns : none
392; Preserve: all registers
393; #########################################################################
394DriveIO_SavePartition Proc Near Uses ax bx cx dx si
395
396IFDEF AUX_DEBUG
397 IF 0
398 DBG_TEXT_OUT_AUX 'DriveIO_SavePartition:'
399 PUSHRF
400 ;~ call DEBUG_DumpRegisters
401 ;~ call AuxIO_DumpParagraph
402 ;~ call AuxIO_TeletypeNL
403 POPRF
404 ENDIF
405ENDIF
406
407 mov ax, wptr cs:[CurPartition_Location+0]
408 mov bx, wptr cs:[CurPartition_Location+2]
409 mov dx, wptr cs:[CurPartition_Location+4]
410 mov cx, wptr cs:[CurPartition_Location+6] ; Gets prev. saved location
411 mov si, offset PartitionSector ; DS:SI - ExecBase
412 cmp wptr [si+LocBR_Magic], 0AA55h ; Checks for signature, if not found
413 jne DIOSP_SevereError ; we assume a really bad error
414 call DriveIO_SaveSector
415 DIOSP_SevereError:
416 ret
417DriveIO_SavePartition EndP
418
419
420
421;##############################################################################
422;# The location of LVM sectors depends on the OS/2 geometry used when the disk
423;# was prepared. This geometry is present in the Master LVM sector, which has
424;# already been located if it exists. All partitions, whether primary or
425;# logical, have an entry in a partition table. For primary partitions this
426;# table is located in the MBR, while for logical partitions this table is
427;# located in the EBR for that logical partition. An LVM record is located
428;# LVM_SPT-1 sectors above an MBR or EBR. The Master LVM record contains the
429;# information for all primary partitions. For logical partitions, the LVM
430;# sector only has one entry, because EBRs are chained. The global LVM info,
431;# like disk-name, sectors per track, etc. is replicated between the Master
432;# LVM sector and LVM sectors corresponding to logical partitions. This info
433;# is kept in sync by the OS/2 LVM Engine.
434;##############################################################################
435;# ACTION : Attempts to load the corresponding LVM sector for a partition
436;# ----------------------------------------------------------------------------
437;# EFFECTS : Modifies DAP structure and fills or clears sector buffer
438;# ----------------------------------------------------------------------------
439;# IN : MEM - Location info is in [CurPartition_Location]
440;# ----------------------------------------------------------------------------
441;# OUT : CF=1 - failure, no valid LVM sector was loaded
442;# : SI - Points to the sector buffer ([LVMSector])
443;##############################################################################
444DriveIO_LoadLVMSector Proc Near Uses ax bx cx dx di
445
446IFDEF AUX_DEBUG
447 IF 1
448 DBG_TEXT_OUT_AUX 'DriveIO_LoadLVMSector:'
449 PUSHRF
450 call DEBUG_DumpRegisters
451 ;~ call AuxIO_DumpSector
452 ;~ call AuxIO_DumpParagraph
453 ;~ call AuxIO_TeletypeNL
454 POPRF
455 ENDIF
456ENDIF
457
458 ; Clear the sector buffer
459 mov si, offset [LVMSector]
460 call ClearSectorBuffer
461
462 ; Quit with CY if LVM is ignored in SETUP
463 test byte ptr [CFG_IgnoreLVM], 1 ; ZF=0 means ignore LVM
464 jnz DIOLLVMS_NoLVMSector ; Quit if so
465
466 ; Load the location of the current partition being acted upon.
467 ; Note that this is not the actual LBA of the partition, but the
468 ; sector that has the partition table that contains the entry
469 ; for the partition. In other words, for primary partitions the LBA
470 ; address points to the MBR while for extended partitions it points
471 ; to an EBR. In both cases the LVM sector is located LVM_SPT-1 above.
472 ; Also note that the BIOS CHS values (DH and CX) below are not used,
473 ; because we explicitly use LBA sector loading.
474 mov ax, wptr cs:[CurPartition_Location+0] ; LBA lo of MBR/EBR
475 mov bx, wptr cs:[CurPartition_Location+2] ; LBA hi of MBR/EBR
476 mov dx, wptr cs:[CurPartition_Location+4] ; BIOS disk num & head
477 mov cx, wptr cs:[CurPartition_Location+6] ; BIOS cyl & sec
478
479 ; Calculate the entry in the DISKINFO array for this disk,
480 ; and put the LVM_SPT in DI
481 push bx
482 call DriveIO_CalcDiskInfoPointer
483 mov di, [bx+LocDISKINFO_LVM_Secs]
484 pop bx
485
486 ; If the LVM_SPT is ZERO, no LVM info is present and we quit with CY
487 test di, di ; See if it is 0
488 jz DIOLLVMS_NoLVMSector ; Quit if so
489
490 ; Adjust the location to point to the LVM sector
491 add ax, di ; Add the LVM sectors-per-track
492 adc bx, 0 ; Propagate LBA lo overflow to LBA hi
493 sub ax, 1 ; LVM sector is located one sector below
494 sbb bx, 0 ; Propagate borrow to LBA hi
495
496 ; Load the LVM sector into [LVMSector]
497 mov si, offset [LVMSector] ; Points to sector buffer
498 mov di, ds ; Segment of that buffer
499 call DriveIO_ReadSectorLBA ; Read the LVM sector
500
501IFDEF AUX_DEBUG
502 IF 1
503 DBG_TEXT_OUT_AUX 'LVMSecLoaded'
504 PUSHRF
505 call DEBUG_DumpRegisters
506 call AuxIO_DumpSector
507 ;~ call AuxIO_DumpParagraph
508 ;~ call AuxIO_TeletypeNL
509 POPRF
510 ENDIF
511ENDIF
512
513 jc DIOLLVMS_NoLVMSector ; Quit on error
514
515 ; Check the validity of the LVM sector, quit with CY if invalid
516 call LVM_ValidateSector ; Check signature and CRC
517 jnc DIOLLVMS_NoLVMSector ; Quit if not valid
518
519 ; We're done, indicate success and return
520 clc
521 jmp DIOLLVMS_Done
522
523 DIOLLVMS_NoLVMSector:
524
525 ; Clear the sector buffer
526 mov si, offset [LVMSector]
527 call ClearSectorBuffer
528 mov bptr [si+LocLVM_SignatureStart], 0
529
530 ; Indicate no valid LVM sector was loaded
531 stc
532
533 DIOLLVMS_Done:
534
535 ret
536DriveIO_LoadLVMSector EndP
537
538
539
540;##############################################################################
541;# The location of LVM sectors depends on the OS/2 geometry used when the disk
542;# was prepared. This geometry is present in the Master LVM sector, which has
543;# already been located if it exists. All partitions, whether primary or
544;# logical, have an entry in a partition table. For primary partitions this
545;# table is located in the MBR, while for logical partitions this table is
546;# located in the EBR for that logical partition. An LVM record is located
547;# LVM_SPT-1 sectors above an MBR or EBR. The Master LVM record contains the
548;# information for all primary partitions. For logical partitions, the LVM
549;# sector only has one entry, because EBRs are chained. The global LVM info,
550;# like disk-name, sectors per track, etc. is replicated between the Master
551;# LVM sector and LVM sectors corresponding to logical partitions. This info
552;# is kept in sync by the OS/2 LVM Engine.
553;##############################################################################
554;# ACTION : Attempts to save the corresponding LVM sector for a partition
555;# ----------------------------------------------------------------------------
556;# EFFECTS : Modifies DAP structure and writes LVM sector to disk
557;# ----------------------------------------------------------------------------
558;# IN : MEM - Location info is in [CurPartition_Location]
559;# : SI - Pointer to sector buffer
560;# ----------------------------------------------------------------------------
561;# OUT : CF=1 - failure, no valid LVM sector was saved
562;##############################################################################
563DriveIO_SaveLVMSector Proc Near Uses ax bx cx dx di
564
565IFDEF AUX_DEBUG
566 IF 1
567 DBG_TEXT_OUT_AUX 'DriveIO_SaveLVMSector:'
568 PUSHRF
569 call DEBUG_DumpRegisters
570 ;~ call AuxIO_DumpParagraph
571 ;~ call AuxIO_TeletypeNL
572 POPRF
573 ENDIF
574ENDIF
575
576 ; Quit with CY if LVM is ignored in SETUP
577 test byte ptr [CFG_IgnoreLVM], 1 ; ZF=0 means ignore LVM
578 jnz DIOSLVMS_SevereError ; Quit if so
579
580 ; Check the validity of the LVM sector, quit with CY if invalid
581 call LVM_ValidateSector ; Check signature and CRC
582 jnc DIOSLVMS_SevereError ; Quit if not valid
583
584 ; Load the location of the current partition being acted upon.
585 ; Note that this is not the actual LBA of the partition, but the
586 ; sector that has the partition table that contains the entry
587 ; for the partition. In other words, for primary partitions the LBA
588 ; address points to the MBR while for extended partitions it points
589 ; to an EBR. In both cases the LVM sector is located LVM_SPT-1 above.
590 ; Also note that the BIOS CHS values (DH and CX) below are not used,
591 ; because we explicitly use LBA sector loading.
592 mov ax, wptr cs:[CurPartition_Location+0] ; LBA lo of MBR/EBR
593 mov bx, wptr cs:[CurPartition_Location+2] ; LBA hi of MBR/EBR
594 mov dx, wptr cs:[CurPartition_Location+4] ; BIOS disk num & head
595 mov cx, wptr cs:[CurPartition_Location+6] ; BIOS cyl & sec
596
597 ; Calculate the entry in the DISKINFO array for this disk,
598 ; and put the LVM_SPT in DI
599 push bx
600 call DriveIO_CalcDiskInfoPointer
601 mov di, [bx+LocDISKINFO_LVM_Secs]
602 pop bx
603
604 ; If the LVM_SPT is ZERO, no LVM info is present and we quit with CY
605 test di, di ; See if it is 0
606 jz DIOSLVMS_SevereError ; Quit if so
607
608 ; Adjust the location to point to the LVM sector
609 add ax, di ; Add the LVM sectors-per-track
610 adc bx, 0 ; Propagate LBA lo overflow to LBA hi
611 sub ax, 1 ; LVM sector is located one sector below
612 sbb bx, 0 ; Propagate borrow to LBA hi
613
614IFDEF AUX_DEBUG
615 IF 1
616 DBG_TEXT_OUT_AUX 'LVMSecSaved'
617 PUSHRF
618 call DEBUG_DumpRegisters
619 call AuxIO_DumpSector
620 ;~ call AuxIO_DumpParagraph
621 ;~ call AuxIO_TeletypeNL
622 POPRF
623 ENDIF
624ENDIF
625
626 ; Save the LVM sector pointed to by SI
627 mov di, ds ; Segment of that buffer
628 call DriveIO_WriteSectorLBA ; Read the LVM sector
629 clc
630 jc DIOSLVMS_SevereError ; Quit on error
631
632 ; We're done, indicate success and return
633 clc
634 jmp DIOSLVMS_Done
635
636 DIOSLVMS_SevereError:
637 ; Indicate no valid LVM sector was saved
638 stc
639
640 DIOSLVMS_Done:
641 ret
642DriveIO_SaveLVMSector EndP
643
644
645
646; Special error message instead of "LOAD ERROR" during partition scanning,
647; so users will notice that something is bad with their partition table(s)
648DriveIO_GotLoadError Proc Near
649 test byte ptr cs:[CurIO_Scanning], 1 ; Must be CS:, cause DS!=CS maybe here
650 jnz InScanMode
651 jmp MBR_LoadError
652 InScanMode:
653 mov si, offset TXT_BrokenPartitionTable
654 push cs
655 pop ds
656 call MBR_Teletype
657 mov si, offset BrokenHDD
658 sub dl, 50h ; 80h -> '0'
659 cmp dl, 39h
660 jbe DIOGLE_BelowA
661 add dl, 7 ; 3Ah -> 'A'
662 DIOGLE_BelowA:
663 mov bptr [si+5], dl
664 call MBR_Teletype
665
666 ; JWasm: cannot jump to local label in other procedure.
667 ; Changed to halt here.
668 ;jmp MBRLE_Halt
669 DriveIO_GotLoadError_halt:
670 jmp DriveIO_GotLoadError_halt
671DriveIO_GotLoadError EndP
672
673; #########################################################################
674; Routine: Loads a specified sector to DS:DI
675; #########################################################################
676; Calling : bx:ax - Absolute sector
677; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
678; ds:si - Destination-Adress
679; Returns : none
680; Preserve: all registers
681; #########################################################################
682DriveIO_LoadSector Proc Near Uses ax bx cx dx ds si es di
683
684IFDEF AUX_DEBUG
685 IF 0
686 DBG_TEXT_OUT_AUX 'DriveIO_LoadSector:'
687 PUSHRF
688 call DEBUG_DumpRegisters
689 ;~ call AuxIO_DumpParagraph
690 ;~ call AuxIO_TeletypeNL
691 POPRF
692 ENDIF
693ENDIF
694
695 ; Is the drive not a harddrive?
696 cmp dl, 80h
697 jb DIOLS_UseNormal
698
699 test byte ptr cs:[CurIO_UseExtension], 1
700 jz DIOLS_UseNormal
701 ; Are we forced do use LBA via Setting?
702 jnz DIOLS_UseExtension
703
704 ; Upper 8 bits of LBA-address set?
705 ; Then use LBA (maximum boundary is 16320x16x63 = FB0400h)
706 or bh, bh
707 jnz DIOLS_UseExtension
708 ; Compare Switch-Table value to bit 16-23 of LBA-address
709 mov di, dx
710 and di, 007Fh
711 cmp bptr cs:[LBASwitchTable+di], bl
712 jbe DIOLS_UseExtension
713
714 DIOLS_UseNormal:
715
716IFDEF AUX_DEBUG
717 IF 0
718 DBG_TEXT_OUT_AUX 'DriveIO_ReadSectorCHS:'
719 PUSHRF
720 call DEBUG_DumpRegisters
721 call AuxIO_DumpParagraph
722 call AuxIO_TeletypeNL
723 POPRF
724 ENDIF
725ENDIF
726
727 mov di, 3 ; retry count
728 DIOLS_ErrorLoop:
729 push ds
730 pop es
731 mov bx, si ; ES:BX - Destination
732 mov ax, 0201h ; Function 2 - Load Sector
733 int 13h
734 jnc DIOLS_Success
735 dec di ; decrement retry count
736 jnz DIOLS_ErrorLoop
737
738 ; Sector load failed...
739 jmp DriveIO_GotLoadError
740
741 DIOLS_UseExtension:
742
743 mov di, ds ; segment for transfer address
744 call DriveIO_ReadSectorLBA ; extended read
745 jc DriveIO_GotLoadError ; halt on error
746
747 ;~ push cx
748 ;~ mov cs:[INT13X_DAP_NumBlocks], 1 ; Copy ONE sector
749 ;~ mov wptr cs:[INT13X_DAP_Transfer+0], si
750 ;~ mov cx, ds
751 ;~ mov wptr cs:[INT13X_DAP_Transfer+2], cx ; Fill out Transfer Adress
752 ;~ mov wptr cs:[INT13X_DAP_Absolute+0], ax
753 ;~ mov wptr cs:[INT13X_DAP_Absolute+2], bx ; Fill out Absolute Sector
754 ;~ push cs
755 ;~ pop ds
756 ;~ mov si, offset [INT13X_DAP]
757 ;~ mov ah, 42h ; Extended Read
758 ;~ int 13h
759 ;~ pop cx
760 ;~ jnc DIOLS_Success
761
762 ; Sector load failed...
763 ;~ jmp DriveIO_GotLoadError
764
765 DIOLS_Success:
766
767IFDEF AUX_DEBUG
768 IF 0
769 DBG_TEXT_OUT_AUX 'sector loaded'
770 PUSHRF
771 ;~ call DEBUG_DumpRegisters
772 ;~ call AuxIO_DumpSector
773 mov cx, 32
774 @@:
775 call AuxIO_DumpParagraph
776 call AuxIO_TeletypeNL
777 add si, 16
778 loop @B
779 POPRF
780 ENDIF
781ENDIF
782 ret
783DriveIO_LoadSector EndP
784
785
786;##############################################################################
787;# ACTION : Loads the Master Boot Record from the specified drive into buffer
788;# ----------------------------------------------------------------------------
789;# EFFECTS : Modifies DAP structure and fills or clears transfer buffer
790;# ----------------------------------------------------------------------------
791;# IN : DL - BIOS disk number (80h,81h,etc)
792;# : SI - Pointer to transfer buffer
793;# ----------------------------------------------------------------------------
794;# OUT : CF=1 - failure
795;# : AL.0 - MBR signature present
796;# : AL.1 - Primary partitions present
797;# : AL.2 - Extended partitions present
798;# : AL.3 - AiR-BOOT signature present
799;# : AL.4:7 - Reserved, returned as 0
800;# : AH.0:7 - Reserved, returned as 0
801;##############################################################################
802DriveIO_LoadMBR Proc Near uses bx cx dx si di
803
804 ; Always clear the transfer buffer first
805 call ClearSectorBuffer
806
807 ; Assume an invalid MBR
808 xor ax, ax
809
810 ; Accept only valid harddisks
811 call DriveIO_IsValidHarddisk
812 jc DriveIO_LoadMBR_exit
813
814 ; Save the address of the transfer buffer
815 mov di, si
816
817 ; Read the MBR from disk
818 xor ax, ax ; LBA low
819 xor bx, bx ; LBA high
820 xor dh, dh ; Head 0
821 mov cx, 1 ; Sector 1
822 call DriveIO_LoadSector ; Read the sector from disk
823
824 ; Check the loaded MBR for a signature
825 xor ax, ax ; Assume an invalid MBR
826 mov dx, [si+LocBR_Magic] ; Get word from MBR signature location
827 cmp dx, 0aa55h ; Is it the magic value ?
828 jne DriveIO_LoadMBR_exit ; Nope, no need to test anything else
829
830 ; Indicate we have a MBR signature
831 or al, 01h
832
833 ; Advance to the partition table
834 add si, 01beh
835
836 ; Total of 4 entries to check
837 mov cx, 4
838
839 DriveIO_LoadMBR_next_entry:
840 mov dl, [si+LocBRPT_SystemID] ; Get partition-type / system-id
841 add si, 10h ; Point to next entry
842 test dl, dl ; Nothing in this one ?
843 loopz DriveIO_LoadMBR_next_entry ; Then check next entry
844
845 ; All entries checked and last one was also empty, we're done
846 jz DriveIO_LoadMBR_check_ab
847
848 ; Found a non-empty entry, set bits according to its type
849 cmp dl, 05h ; Old style extended container ?
850 jne @F ; Nope...
851 or al, 04h ; Yep, mark ext. container present
852 @@: cmp dl, 0fh ; New style extended container ?
853 jne @F ; Nope...
854 or al, 04h ; Yep, mark ext. container present
855 @@: or al, 02h ; Then is must be a primary
856 jcxz DriveIO_LoadMBR_check_ab ; CX=0? Then all entries processed,
857 jmp DriveIO_LoadMBR_next_entry ; otherwise check next entry
858
859 ; Check if an AiR-BOOT signature is present
860 DriveIO_LoadMBR_check_ab:
861 mov si, offset [MBR_ABSig] ; Offset of AiR-BOOT signature
862 inc di ; Advance buffer pointer
863 inc di ; to AiR-BOOT signature location
864 mov cx, 7 ; Length of AiR-BOOT signature
865 cld ; Direction upwards
866 repe cmpsb ; Compare 7 bytes
867 jne DriveIO_LoadMBR_exit ; Nope, no AiR-BOOT on this disk
868 or al, 08h ; Yep, AiR-BOOT is on this disk
869 ;~ jmp DriveIO_LoadMBR_exit
870
871 DriveIO_LoadMBR_exit:
872 ret
873DriveIO_LoadMBR EndP
874
875
876;##############################################################################
877;# ACTION : Reads a sector from disk using INT13 extensions
878;# ----------------------------------------------------------------------------
879;# EFFECTS : Modifies DAP structure and fills transfer buffer
880;# ----------------------------------------------------------------------------
881;# IN : BX:AX - LBA address of sector
882;# : DI:SI - SEG:OFF of transfer buffer
883;# ----------------------------------------------------------------------------
884;# OUT : CF=1 - failure
885;##############################################################################
886DriveIO_ReadSectorLBA Proc Near
887
888IFDEF AUX_DEBUG
889 IF 0
890 DBG_TEXT_OUT_AUX 'DriveIO_ReadSectorLBA:'
891 PUSHRF
892 call DEBUG_DumpRegisters
893 call AuxIO_DumpParagraph
894 call AuxIO_TeletypeNL
895 POPRF
896 ENDIF
897ENDIF
898
899 ; Push all registers
900 pusha
901 push ds
902 push es
903
904 ; One sector to read
905 mov cs:[INT13X_DAP_NumBlocks], 1
906
907 ; Setup transfer address
908 mov wptr cs:[INT13X_DAP_Transfer+0], si ; offset
909 mov wptr cs:[INT13X_DAP_Transfer+2], di ; segment
910
911 ; Setup LBA64 address of requested sector
912 mov wptr cs:[INT13X_DAP_Absolute+0], ax ; low word lower part
913 mov wptr cs:[INT13X_DAP_Absolute+2], bx ; high word lower part
914 mov wptr cs:[INT13X_DAP_Absolute+4], 0 ; low word upper part
915 mov wptr cs:[INT13X_DAP_Absolute+6], 0 ; high word upper part
916
917 ; Address of packet
918 mov si, offset [INT13X_DAP] ; disk address packet
919
920 ; Do the extended read
921 mov ah, 42h ; read function
922 int 13h ; transfer to bios
923
924 ; Error occured
925 jc DriveIO_ReadSectorLBA_exit
926
927 ; AH should also be zero
928 test ah, ah
929 stc
930 jnz DriveIO_ReadSectorLBA_exit
931
932 ; Disk read succeeded, clear CF
933 clc
934
935 DriveIO_ReadSectorLBA_exit:
936
937 ; Pop all registers
938 pop es
939 pop ds
940 popa
941
942 ret
943DriveIO_ReadSectorLBA EndP
944
945
946
947;##############################################################################
948;# ACTION : Writes a sector to disk using INT13 extensions
949;# ----------------------------------------------------------------------------
950;# EFFECTS : Modifies DAP structure and mofifies the disk
951;# ----------------------------------------------------------------------------
952;# IN : BX:AX - LBA address of sector
953;# : DI:SI - SEG:OFF of transfer buffer
954;# ----------------------------------------------------------------------------
955;# OUT : CF=1 - failure
956;##############################################################################
957DriveIO_WriteSectorLBA Proc Near
958
959IFDEF AUX_DEBUG
960 IF 0
961 DBG_TEXT_OUT_AUX 'DriveIO_WriteSectorLBA:'
962 PUSHRF
963 call DEBUG_DumpRegisters
964 call AuxIO_DumpParagraph
965 call AuxIO_TeletypeNL
966 POPRF
967 ENDIF
968ENDIF
969
970 ; Push all registers
971 pusha
972 push ds
973 push es
974
975 ; One sector to read
976 mov cs:[INT13X_DAP_NumBlocks], 1
977
978 ; Setup transfer address
979 mov wptr cs:[INT13X_DAP_Transfer+0], si ; offset
980 mov wptr cs:[INT13X_DAP_Transfer+2], di ; segment
981
982 ; Setup LBA64 address of requested sector
983 mov wptr cs:[INT13X_DAP_Absolute+0], ax ; low word lower part
984 mov wptr cs:[INT13X_DAP_Absolute+2], bx ; high word lower part
985 mov wptr cs:[INT13X_DAP_Absolute+4], 0 ; low word upper part
986 mov wptr cs:[INT13X_DAP_Absolute+6], 0 ; high word upper part
987
988 ; Address of packet
989 mov si, offset [INT13X_DAP] ; disk address packet
990
991 ; Do the extended write
992 xor al, al ; no write verify
993 mov ah, 43h ; write function
994 int 13h ; transfer to bios
995
996 ; Error occured
997 jc DriveIO_WriteSectorLBA_exit
998
999 ; AH should also be zero
1000 test ah, ah
1001 stc
1002 jnz DriveIO_WriteSectorLBA_exit
1003
1004 ; Disk write succeeded, clear CF
1005 clc
1006
1007 DriveIO_WriteSectorLBA_exit:
1008
1009 ; Pop all registers
1010 pop es
1011 pop ds
1012 popa
1013
1014 ret
1015DriveIO_WriteSectorLBA EndP
1016
1017
1018
1019
1020;##############################################################################
1021;# The Master LVM sector is *not* necessarily located at the end of the BIOS
1022;# view of TRACK0. Its location depends on the *OS/2 geometry* active when the
1023;# disk was partitioned. For disks < 502MiB this will most likely be LBA sector
1024;# 62, but for disks >502MiB, *extended* OS/2 geometry was used and DANIS506
1025;# uses SPT=127 for disks < 1TiB while IBMS506 uses SPT=255.
1026;# When a huge disk < 1TiB was partitioned with IBMS506, thus using SPT=255,
1027;# and the driver was later changed to DANIS506, DANI uses SPT=255, eventhough
1028;# the disk < 1TiB. Whether it is DANI that is LVM aware or something else
1029;# (maybe LVM itself) that makes DANI use the correct geometry has yet to be
1030;# investigated.
1031;#
1032;# Related geometry issues are also present with USB sticks, which can get
1033;# assigned a geometry by OS/2, which can depend if the stick was partitioned
1034;# on foreign systems or not, or even OS/2 manufacturing a geometry that is not
1035;# the same as the BIOS reports to us here. In both cases, fixed disks and
1036;# removable disks, the geometry recorded in the BPB of a partition can also
1037;# influence the geometry that OS/2 assigns. This is the case when 'preparing'
1038;# disks for LVM use, in which case BPB values could be incorporated.
1039;#
1040;# What this all boils down to, is that the geometry reported by the BIOS is
1041;# of no practical use, especially not when taking BIOS USB MSD emulation into
1042;# account. These are among the reasons why AirBoot needs to use LBA addressing
1043;# when handling LVM stuff and why LBA use cannot be disabled in the SETUP
1044;# anymore.
1045;#
1046;# So, a Master LVM sector can be present on any sector from LBA 254 downwards
1047;# and the only way to locate the correct one is to scan all the way down and,
1048;# if one is found, do proper validation on its values, because it may also be
1049;# a 'phantom' LVM sector left over from previous partition layouts.
1050;# Most of such 'phantoms' can be filtered out by verifying the location of
1051;# the found sector against the OS/2 geometry it specifies itself, which means
1052;# it must be located at the LBA of the SPT-1 it specifies.
1053;##############################################################################
1054;# ACTION : Locates the Master LVM sector on the specified disk
1055;# ----------------------------------------------------------------------------
1056;# EFFECTS : Leaves [Scratch] with last sector read or cleared
1057;# ----------------------------------------------------------------------------
1058;# IN : DL - BIOS disk number of drive to search
1059;# ----------------------------------------------------------------------------
1060;# OUT : CF=1 - found
1061;# : BX:AX - LBA address of LVM sector if found, 0 otherwise
1062;##############################################################################
1063DriveIO_LocateMasterLVMSector Proc Near uses cx dx si di ds es
1064
1065IFDEF AUX_DEBUG
1066 IF 1
1067 DBG_TEXT_OUT_AUX 'DriveIO_LocateMasterLVMSector:'
1068 PUSHRF
1069 call DEBUG_DumpRegisters
1070 ;~ call AuxIO_DumpSector
1071 ;~ call AuxIO_DumpParagraph
1072 ;~ call AuxIO_TeletypeNL
1073 POPRF
1074 ENDIF
1075ENDIF
1076
1077 ; LBA address to start scanning down from
1078 mov cx, 255
1079
1080 ; Make sure ES==DS
1081 push ds
1082 pop es
1083
1084 ; Because JCXZ is used, LBA sector 0 is never loaded and checked.
1085 ; This is of course no problem since it is the MBR.
1086 DriveIO_LocateMasterLVMSector_next:
1087 mov si, offset [Scratch] ; Use scratch area to load sectors
1088 call ClearSectorBuffer ; Clear the scratch area
1089 clc ; Indicate Master LVM sector not found
1090 jcxz DriveIO_LocateMasterLVMSector_done
1091
1092 ; Read the LBA sector specified in CX
1093 mov ax, cx ; LBA low
1094 xor bx, bx ; LBA high
1095 mov di, ds ; Segment of scratch buffer
1096 mov si, offset [Scratch] ; Offset of scratch buffer
1097 call DriveIO_ReadSectorLBA ; Read the sector
1098 lahf ; Save CF
1099 dec cx ; Prepare LBA of next sector to read
1100 sahf ; Restore CF
1101 ; No need to do any LVM sector validation when read error, read next
1102 jc DriveIO_LocateMasterLVMSector_next
1103
1104 ; See if the read sector has a valid signature and checksum
1105 call LVM_ValidateSector
1106
1107 ; NC indicates invalid or none-LVM sector, read next
1108 jnc DriveIO_LocateMasterLVMSector_next
1109
1110 ; We have found a valid LVM sector !
1111 ; So it contains the OS/2 geometry for the disk.
1112 ; That means this LVM sector itself must be located on the last sector
1113 ; of the SPT value its OS/2 geometery specifies, which, in LBA terms
1114 ; is LVM SPT-1 -- let's check that...
1115 mov bx, offset [Scratch] ; Offset of the loaded LVM sector
1116 mov al, [bx+LocLVM_Secs] ; Get the LVM SPT value (<=255)
1117 dec al ; Adjust to LVM LBA
1118 mov ah, cl ; Get next LVM LBA to search
1119 inc ah ; This one was found here
1120 cmp al, ah ; If same, LVM LBA location OK
1121 jne DriveIO_LocateMasterLVMSector_next
1122
1123 ; The LVM sector we found is at the location it should be on disk,
1124 ; so it's almost 99% sure this is the correct one.
1125 ; Now we should compare the start and sizes of the partitions in the
1126 ; MBR with the partitions specified in this LVM record.
1127 ; We'll implement that later after some more research.
1128 ; For now we assume this is the correct Master LVM sector for the disk.
1129 inc cx ; CX was prepared to read next, correct that
1130 stc ; Indicate we have found the Master LVM sector
1131
1132 DriveIO_LocateMasterLVMSector_done:
1133 mov bx, 0 ; A Master LVM sector always has high LBA=0
1134 mov ax, cx ; Low LBA of Master LVM sector
1135
1136 ; We leave it up to the caller to store the value in a proper place
1137 ret
1138DriveIO_LocateMasterLVMSector EndP
1139
1140
1141
1142;
1143; ############################################################
1144; # Check for a valid MBR-sector to be written to disk #
1145; ############################################################
1146;
1147; In
1148; --
1149; DL = Physical Disk
1150; BX:CX = LBA sector
1151; DI:SI = Source buffer
1152;
1153; Out
1154; ---
1155; CY = 1 if invalid MBR in source buffer, 0 if valid
1156;
1157; This routine is called when DriveIO_SaveSector attempts to write to the MBR.
1158; It checks if the sector to be written has some sensible values in certain
1159; places. In fact, if the sector is written to the boot-disk, the AiR-BOOT
1160; signature should be present and the partition table should be the same
1161; as the one at the start of the AiR-BOOT code in memory, except maybe for the
1162; active flags.
1163; For other disks, only the active flags are checked to be 00h or 80h and
1164; the AA55h MBR signature.
1165;
1166DriveIO_ProtectMBR Proc Near
1167 pusha ; Push all registers
1168 push es ; Push ES because we need it for string instructions
1169 push cs ; Make ES point...
1170 pop es ; to CS
1171
1172 ; Save the pointer to the sector to write in BX
1173 mov bx,si
1174
1175 ;
1176 ; If the sector to be written is not the boot-disk, then skip
1177 ; checking the AiR-BOOT MBR.
1178 ;
1179 cmp dl, [BIOS_BootDisk]
1180 jne DriveIO_ProtectMBR_is_not_bootdisk
1181
1182 ;
1183 ; The boot-disk is accessed so the sector to be written must be
1184 ; the AiR-BOOT MBR. This is the same as the first 512 bytes
1185 ; relocated to 8000:0000 and this the start of the AB-code.
1186 ;
1187 mov si,bx ; Get pointer to sector to write
1188 xor di,di ; Point DI to start of AB-code (MBR)
1189 mov cx, offset [MBR_PartTable] ; Bytes upto P-table must be same
1190 cld ; Compare upwards
1191 repe cmpsb ; Compare upto P-table
1192
1193 ; If not the same this is not the an AiR-BOOT boot-disk MBR !
1194 jne DriveIO_ProtectMBR_not_valid_MBR ; SEVERE ERROR !
1195
1196 ; Continue with signature check
1197 jmp DriveIO_ProtectMBR_check_signature
1198
1199
1200 ;
1201 ; The disk is not the boot-disk so we don't know what kind of MBR is on it.
1202 ; Some sanity checks should be here.
1203 ;
1204 DriveIO_ProtectMBR_is_not_bootdisk:
1205
1206 ;
1207 ; sanity checks...
1208 ;
1209
1210 ; Continue with signature check
1211 jmp DriveIO_ProtectMBR_check_signature
1212
1213
1214 DriveIO_ProtectMBR_check_signature:
1215 ; See if the sector to write contains a valid signature
1216 mov si,bx ; Get pointer to sector to write
1217 mov di, offset [MBR_Sig] ; Offset to MBR signature
1218 add si,di ; Make SI point to it in sec to write
1219 lodsw ; Load it
1220 cmp ax,0aa55h ; See if it is valid
1221
1222 ; If no signature this cannot be a valid MBR !
1223 jne DriveIO_ProtectMBR_not_valid_MBR ; SEVERE ERROR !
1224
1225
1226 ;
1227 ; The sector to be written seems to be valid.
1228 ; Set CY=0 to indicate a valid MBR.
1229 ;
1230 DriveIO_ProtectMBR_is_valid_MBR:
1231 clc
1232 jmp DriveIO_ProtectMBR_end
1233
1234 ;
1235 ; Something is terribly wrong; a non-MBR sector seems about to be written.
1236 ; Set CY=1 and let the calling code handle this situation.
1237 ;
1238 DriveIO_ProtectMBR_not_valid_MBR:
1239 stc
1240 jmp DriveIO_ProtectMBR_end
1241
1242 ;
1243 ; Return to the caller with no registers modyfied except FLAGS.
1244 ;
1245 DriveIO_ProtectMBR_end:
1246 pop es
1247 popa
1248 ret
1249DriveIO_ProtectMBR Endp
1250
1251
1252
1253; #########################################################################
1254; Routine: Checks if the MBR is addressed by either CHS or LBA
1255; #########################################################################
1256; Calling : bx:ax - Absolute sector
1257; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
1258; Returns : ZF=1 if MBR is addressed, else ZF=0
1259; Preserve: all registers
1260; #########################################################################
1261DriveIO_MBR_Addressed Proc
1262 push ax
1263 push bx
1264
1265 or bx,ax ; Results in 0 in BX if MBR is addressed by LBA
1266 jz DriveIO_MBR_Addressed_done
1267
1268 mov ax,cx ; Results in 1 in AX if CYL 0, SEC 1 is addressed
1269 add al,dh ; Results in 1 in AX if HEAD 0 is addressed
1270 dec ax ; Results in 0 in AX if MBR is addressed by CHS
1271
1272 DriveIO_MBR_Addressed_done:
1273 pop bx
1274 pop ax
1275 ret
1276DriveIO_MBR_Addressed EndP
1277
1278
1279
1280
1281; #########################################################################
1282; Routine: Writes DS:SI to a specified sector
1283; #########################################################################
1284; Calling : bx:ax - Absolute sector
1285; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
1286; ds:si - Source-Adress
1287; Returns : none
1288; Preserve: all registers
1289; #########################################################################
1290DriveIO_SaveSector Proc Near Uses ax bx cx dx ds si es di
1291
1292IFDEF AUX_DEBUG
1293 IF 0
1294 DBG_TEXT_OUT_AUX 'DriveIO_SaveSector:'
1295 PUSHRF
1296 ;~ call DEBUG_DumpRegisters
1297 ;~ call AuxIO_DumpParagraph
1298 ;~ call AuxIO_TeletypeNL
1299 POPRF
1300 ENDIF
1301ENDIF
1302
1303
1304;!
1305;! DEBUG_BLOCK
1306;! Force write to LBA0 to test interception routine.
1307;! Do *NOT* enable unless you are debugging, will overwrite MBR !
1308;!
1309IFDEF AUX_DEBUG
1310 IF 0
1311 pushf
1312 pusha
1313 xor ax,ax
1314 xor bx,bx
1315 xor cx,cx
1316 inc cx
1317 xor dh,dh
1318 popa
1319 popf
1320 ENDIF
1321ENDIF
1322
1323 ;
1324 ; Check if the MBR is the destination for the write.
1325 ; ZF=1 if so.
1326 ;
1327 call DriveIO_MBR_Addressed
1328 jnz DriveIO_SaveSector_continue_write
1329
1330
1331 ; MBR is addressed, check the sector that is requested to be written.
1332 ; For the bootdisk it should contain the AiR-BOOT signature, valid
1333 ; partition-table entries and the AA55h signature.
1334 ; If not, something is terribly wrong in some piece of the AB code.
1335 ; For any other disk (80h+) at least a valid partition table should
1336 ; be present together with the AA55h signature.
1337 call DriveIO_ProtectMBR
1338 jnc DriveIO_SaveSector_continue_write
1339
1340
1341 ;
1342 ; WE HAVE A SEVERE ERROR CONDITION !
1343 ; SOME AB CODE TRIES TO WRITE A NON-MBR TO THE DISK !
1344 ; ASK THE USER TO REPORT THIS !
1345 ; HALT THE SYSTEM !
1346 ;
1347
1348 ; Show error-box
1349 mov cx, 0C04h
1350 mov si, offset NonMBRwrite
1351 call SETUP_ShowErrorBox
1352 mov cx, 0C04h
1353 mov si, offset NonMBRwrite_rep
1354 call SETUP_ShowErrorBox
1355
1356
1357IFDEF AUX_DEBUG
1358 IF 0
1359 pushf
1360 pusha
1361 mov si, offset [NonMBRwrite]
1362 call AuxIO_TeletypeNL
1363 call AuxIO_Print
1364 call AuxIO_TeletypeNL
1365 popa
1366 popf
1367 ENDIF
1368ENDIF
1369
1370 ; Show popup and halt the system.
1371 jmp HaltSystem
1372
1373
1374
1375 ;
1376 ; Continue the write if not MBR sector or MBR to write is validated.
1377 ;
1378 DriveIO_SaveSector_continue_write:
1379 test byte ptr cs:[CurIO_UseExtension], 1
1380 jz DIOSS_UseNormal
1381 ; Are we forced do use LBA via Setting?
1382 ; Always use INT13X on v1.0.8+.
1383 ;~ test byte ptr cs:[CFG_ForceLBAUsage], 1
1384 ;~ jnz DIOSS_UseExtension
1385 jmp DIOSS_UseExtension
1386 ; Is the drive not a harddrive?
1387 cmp dl, 80h
1388 jb DIOSS_UseNormal
1389 ; Upper 8 bits of LBA-address set? -> Use LBA (maximum boundary is FB0400h)
1390 or bh, bh
1391 jnz DIOSS_UseExtension
1392 ; Compare Switch-Table value to bit 16-23 of LBA-address
1393 mov di, dx
1394 and di, 007Fh
1395 cmp bptr cs:[LBASwitchTable+di], bl
1396 jbe DIOSS_UseExtension
1397
1398 DIOSS_UseNormal:
1399
1400IFDEF AUX_DEBUG
1401 IF 0
1402 DBG_TEXT_OUT_AUX 'DriveIO_WriteSectorCHS:'
1403 PUSHRF
1404 call DEBUG_DumpRegisters
1405 call AuxIO_DumpParagraph
1406 call AuxIO_TeletypeNL
1407 POPRF
1408 ENDIF
1409ENDIF
1410
1411 mov di, 3 ; retry count
1412 DIOSS_ErrorLoop:
1413 push ds
1414 pop es
1415 mov bx, si ; ES:BX - Destination
1416 mov ax, 0301h ; Function 3 - Write Sector
1417 int 13h
1418 jnc DIOSS_Success
1419 dec di ; decrement retry count
1420 jnz DIOSS_ErrorLoop
1421 call MBR_SaveError
1422
1423 DIOSS_UseExtension:
1424
1425 mov di, ds ; segment for transfer address
1426 call DriveIO_WriteSectorLBA ; extended write
1427 jc MBR_SaveError ; halt on error
1428
1429 ;~ push cx
1430 ;~ mov cs:[INT13X_DAP_NumBlocks], 1 ; Copy ONE sector
1431 ;~ mov wptr cs:[INT13X_DAP_Transfer+0], si
1432 ;~ mov cx, ds
1433 ;~ mov wptr cs:[INT13X_DAP_Transfer+2], cx ; Fill out Transfer Adress
1434 ;~ mov wptr cs:[INT13X_DAP_Absolute+0], ax
1435 ;~ mov wptr cs:[INT13X_DAP_Absolute+2], bx ; Fill out Absolute Sector
1436 ;~ push cs
1437 ;~ pop ds
1438 ;~ mov si, offset [INT13X_DAP]
1439 ;~ mov ax, 4300h ; Extended Write (No Verify)
1440 ;~ int 13h
1441 ;~ pop cx
1442 ;~ jnc DIOSS_Success
1443 ;~ call MBR_SaveError
1444
1445 DIOSS_Success:
1446 ret
1447DriveIO_SaveSector EndP
1448
1449
1450
1451
1452;##############################################################################
1453;# When a disk has a Master LVM sector, it means it has been prepared for use
1454;# by OS/2 and contains important information about how OS/2 views its geometry
1455;# and other disk related properties. This function assumes the LBA address
1456;# of the Master LVM sector has already been located and simply loads the
1457;# sector into [LVMSector].
1458;#
1459;# Note that because this is an operation similar to the regular loading of
1460;# sectors, the disk I/O semantics are used here. This means CF=0 when an LVM
1461;# sector is successfully loaded and CF=1 otherwise.
1462;##############################################################################
1463;# ACTION : Loads the Master LVM sector if one exists
1464;# ----------------------------------------------------------------------------
1465;# EFFECTS : Modifies DAP structure and [LVMSector]
1466;# ----------------------------------------------------------------------------
1467;# IN : DL - BIOS disk number (80h,81h,etc)
1468;# ----------------------------------------------------------------------------
1469;# OUT : CF=0 - Valid Master LVM sector found and loaded
1470;##############################################################################
1471DriveIO_LoadMasterLVMSector Proc Near
1472
1473IFDEF AUX_DEBUG
1474 IF 0
1475 DBG_TEXT_OUT_AUX 'DriveIO_LoadMasterLVMSector:'
1476 PUSHRF
1477 ;~ call DEBUG_DumpRegisters
1478 ;~ call AuxIO_DumpParagraph
1479 ;~ call AuxIO_TeletypeNL
1480 POPRF
1481 ENDIF
1482ENDIF
1483
1484 ; Save all registers
1485 pusha
1486
1487 ; Check if BIOS disk number is valid
1488 call DriveIO_IsValidHarddisk
1489 jc DriveIO_LoadMasterLVMSector_error
1490
1491 ; Calculate the entry in the DISKINFO array for this disk
1492 call DriveIO_CalcDiskInfoPointer
1493
1494 ; Save the entry for later recalls
1495 mov bp, bx
1496
1497 ; Get the LBA address of the Master LVM sector
1498 mov ax, [bx+LocDISKINFO_LVM_MasterLBA+00h]
1499 mov bx, [bx+LocDISKINFO_LVM_MasterLBA+02h]
1500
1501 ; LBA of Master LVM sector cannot be 0, so none was found during
1502 ; the gathering of disk information.
1503 mov cx, ax
1504 or cx, bx
1505 jz DriveIO_LoadMasterLVMSector_error
1506
1507 ; Load it into [LVMSector]
1508 mov di, ds
1509 mov si, offset [LVMSector]
1510 call DriveIO_ReadSectorLBA
1511 jc DriveIO_LoadMasterLVMSector_error
1512
1513 ; Validate the Master LVM sector
1514 call LVM_ValidateSector
1515
1516 ; Complement success indicator to conform to semantics of this function
1517 cmc
1518
1519 ; Master LVM sector was valid and is now loaded in [LVMSector]
1520 jnc DriveIO_LoadMasterLVMSector_ret
1521
1522 DriveIO_LoadMasterLVMSector_error:
1523
1524 ; Clear the sector buffer for safety reasons
1525 mov si, offset [LVMSector]
1526 call ClearSectorBuffer
1527
1528 ; Indicate no Master LVM sector loaded
1529 stc
1530
1531 DriveIO_LoadMasterLVMSector_ret:
1532
1533 ; Restore all registers
1534 popa
1535
1536 ret
1537DriveIO_LoadMasterLVMSector Endp
1538
1539
1540
1541
1542;##############################################################################
1543;# There is much information to know about the connected disks.
1544;# We also want this information clustered per disk and available before
1545;# further disk and partition scanning takes place.
1546;# This function gathers such information like INT13, INT13X, MBR, LVM, more.
1547;# Especially important is the LVM information, because that contains the
1548;# geometry OS/2 uses to access the disk. Other important information is the
1549;# presence of valid MBRs, logical partitions and whatnot.
1550;# This function gathers such information and stores it in a DISKINFO structure
1551;# for which an instance exists for every disk found.
1552;##############################################################################
1553;# ACTION : Gather disk information and store this in the BSS
1554;# ----------------------------------------------------------------------------
1555;# EFFECTS : Modifies DAP structure and the buffers it uses, fills DISKINFO[n]
1556;# ----------------------------------------------------------------------------
1557;# IN : DL - BIOS disk number (80h,81h,etc)
1558;# ----------------------------------------------------------------------------
1559;# OUT : CF=1 - failure
1560;##############################################################################
1561DriveIO_GatherDiskInfo Proc Near
1562
1563IFDEF AUX_DEBUG
1564 IF 1
1565 DBG_TEXT_OUT_AUX 'DriveIO_GatherDiskInfo:'
1566 PUSHRF
1567 call DEBUG_DumpRegisters
1568 ;~ call AuxIO_DumpParagraph
1569 ;~ call AuxIO_TeletypeNL
1570 POPRF
1571 ENDIF
1572ENDIF
1573
1574 ; Push all registers we use
1575 pusha
1576 push ds
1577 push es
1578
1579 ; Make sure ES=DS
1580 push ds
1581 pop es
1582
1583 ; Check if BIOS disk number is valid
1584 call DriveIO_IsValidHarddisk
1585 jc DriveIO_GatherDiskInfo_error
1586
1587 ; Calculate the entry in the DISKINFO array for this disk
1588 call DriveIO_CalcDiskInfoPointer
1589
1590 ; Save the entry for later recalls
1591 mov bp, bx
1592
1593 ; Store the BIOS disk number in the structure
1594 mov [bx+LocDISKINFO_DiskNum], dl
1595
1596; ------------------------------------------------------------------- [ INT13 ]
1597
1598 ; Get BIOS Disk Parameters (legacy method)
1599 mov ah, 08h ; Get Disk Parameters
1600 int 13h ; Call BIOS
1601
1602 ; CF=1 or AH!=0 indicates error
1603 jc DriveIO_GatherDiskInfo_error
1604 test ah, ah
1605 jnz DriveIO_GatherDiskInfo_error
1606
1607 ; Recall DISKINFO entry
1608 mov bx, bp
1609
1610 ; Store SPT (WORD)
1611 xor ah, ah ; Zero extend SPT to 16 bits
1612 mov al, cl ; Hi 2 bits max cyl and max sec
1613 and al, 3fh ; Mask max sec (1-based)
1614 mov [bx+LocDISKINFO_I13_Secs], ax ; Store SPT
1615
1616 ; Store HEADS (WORD)
1617 xor dl, dl ; Zero extend HEADS to 16 bits
1618 xchg dl, dh ; Get max head (0-based)
1619 inc dx ; Head count
1620 mov [bx+LocDISKINFO_I13_Heads], dx ; Store HEADS
1621
1622 ; Store CYLS (WORD)
1623 shr cl, 6 ; Hi 2 bits of max cyl to 1:0
1624 xchg cl, ch ; Max cyl (0-based)
1625 inc cx ; Cyl count
1626 mov [bx+LocDISKINFO_I13_Cyls], cx ; Store CYLS
1627
1628 ; Recall BIOS disk number
1629 mov dl, [bx+LocDISKINFO_DiskNum]
1630
1631; ------------------------------------------------------------------ [ INT13X ]
1632
1633 ; Get BIOS Disk Parameters (extended method)
1634 mov si, offset [Scratch] ; Buffer to return disk info
1635 mov ax, 80h ; Size of buffer
1636 mov [si], ax ; Store it in first word
1637 mov ah, 48h ; Get Extended Disk Parameters
1638 int 13h ; Call BIOS
1639
1640 ; CF=1 or AH!=0 indicates error
1641 jc DriveIO_GatherDiskInfo_error
1642 test ah, ah
1643 jnz DriveIO_GatherDiskInfo_error
1644
1645 ; Store flags (WORD)
1646 cld ; Direction up
1647 lodsw ; Buffersize, discard
1648 lodsw ; Flags (CHS valid etc)
1649 mov [bx+LocDISKINFO_I13X_Flags], ax ; Store them
1650
1651 ; Store CYLS (DWORD)
1652 lodsw ; Cyl count low
1653 mov [bx+LocDISKINFO_I13X_Cyls+00h], ax ; Store CYLS low
1654 lodsw ; Cyl count high
1655 mov [bx+LocDISKINFO_I13X_Cyls+02h], ax ; Store CYLS high
1656
1657 ; Store HEADS (DWORD)
1658 lodsw ; Head count low
1659 mov [bx+LocDISKINFO_I13X_Heads+00h], ax ; Store HEADS low
1660 lodsw ; Head count high
1661 mov [bx+LocDISKINFO_I13X_Heads+02h], ax ; Store HEADS high
1662
1663 ; Store SPT (DWORD)
1664 lodsw ; Secs per track low
1665 mov [bx+LocDISKINFO_I13X_Secs+00h], ax ; Store SPT low
1666 lodsw ; Secs per track high
1667 mov [bx+LocDISKINFO_I13X_Secs+02h], ax ; Store SPT high
1668
1669 ; Store total LBA sectors (QWORD)
1670 lea di, [bx+LocDISKINFO_I13X_SecsLBA]
1671 mov cx, 4
1672 rep movsw
1673
1674 ; Store sector size (WORD)
1675 lodsw
1676 mov [bx+LocDISKINFO_I13X_SecSize], ax
1677
1678 ; Store bus name (4 bytes, space padded, v3.0+)
1679 lea si, [Scratch+24h]
1680 lea di, [bx+LocDISKINFO_I13X_HostBus]
1681 movsw
1682 movsw
1683
1684 ; Store interface name (8 bytes, space padded, v3.0+)
1685 lea di, [bx+LocDISKINFO_I13X_Interface]
1686 mov cx, 4
1687 rep movsw
1688
1689 ; Should gather some more INT13X info here,
1690 ; like maybe Advanced Format stuff or so.
1691 ; We'll investigate that at a later time.
1692
1693; --------------------------------------------------------------------- [ MBR ]
1694
1695 ; Load the MBR
1696 mov si, offset [TmpSector]
1697 call DriveIO_LoadMBR
1698
1699 ; Store MBR flags (valid sig, partitions present, airboot installed)
1700 mov [bx+LocDISKINFO_MbrFlags], al
1701
1702 ; Recall BIOS disk number
1703 mov dl, [bx+LocDISKINFO_DiskNum]
1704
1705; --------------------------------------------------------------------- [ LVM ]
1706
1707 ; Locate the Master LVM sector, if any
1708 call DriveIO_LocateMasterLVMSector
1709
1710 ; Save Master LVM sector LBA high
1711 mov cx, bx
1712
1713 ; Recall DISKINFO entry
1714 mov bx, bp
1715
1716 ; Store Master LVM sector LBA
1717 mov [bx+LocDISKINFO_LVM_MasterLBA+00h], ax
1718 mov [bx+LocDISKINFO_LVM_MasterLBA+02h], cx
1719
1720 ; No Master LVM sector found, so skip storing LVM info for this disk
1721 jnc DriveIO_GatherDiskInfo_no_master_lvm
1722
1723 ; Load the Master LVM sector into [LVMSector]
1724 call DriveIO_LoadMasterLVMSector
1725
1726 ; No valid Master LVM sector, so skip storing LVM info for this disk
1727 jc DriveIO_GatherDiskInfo_no_master_lvm
1728
1729 ; A valid Master LVM sector has been loaded into [LVMSector]
1730 mov si, offset [LVMSector]
1731
1732 ; Get the number of sectors per track (OS/2 geometry)
1733 mov ax, [si+LocLVM_Secs+00h]
1734 mov cx, [si+LocLVM_Secs+02h]
1735
1736 ; Store it
1737 mov [bx+LocDISKINFO_LVM_Secs+00h], ax
1738 mov [bx+LocDISKINFO_LVM_Secs+02h], cx
1739
1740 ; Get the number of heads (OS/2 geometry)
1741 mov ax, [si+LocLVM_Heads+00h]
1742 mov cx, [si+LocLVM_Heads+02h]
1743
1744 ; Store it
1745 mov [bx+LocDISKINFO_LVM_Heads+00h], ax
1746 mov [bx+LocDISKINFO_LVM_Heads+02h], cx
1747
1748 ; Should gather some more LVM info here,
1749 ; like OS/2 extended geometry and other flags.
1750 ; We'll implement that at a later time.
1751
1752 DriveIO_GatherDiskInfo_no_master_lvm:
1753
1754 ; When no Master LVM sector was found,
1755 ; the LVM info in the DISKINFO structure for the disk
1756 ; will be ZERO because the area was cleared in PRECRAP.
1757
1758 ; Indicate success
1759 clc
1760
1761 jmp DriveIO_GatherDiskInfo_ret
1762
1763 DriveIO_GatherDiskInfo_error:
1764 stc
1765 DriveIO_GatherDiskInfo_ret:
1766
1767
1768IFDEF AUX_DEBUG
1769 IF 1
1770 DBG_TEXT_OUT_AUX '[DISKINFO]'
1771 PUSHRF
1772 call DEBUG_DumpRegisters
1773 ;~ call AuxIO_DumpParagraph
1774 ;~ call AuxIO_TeletypeNL
1775 mov si, bp
1776 mov cx, 4
1777 @@:
1778 call AuxIO_DumpParagraph
1779 call AuxIO_TeletypeNL
1780 add si, 16
1781 loop @B
1782 mov si, offset [Scratch]
1783 mov cx, 4
1784 @@:
1785 call AuxIO_DumpParagraph
1786 call AuxIO_TeletypeNL
1787 add si, 16
1788 loop @B
1789 mov si, offset [LVMSector]
1790 mov cx, 7
1791 @@:
1792 call AuxIO_DumpParagraph
1793 call AuxIO_TeletypeNL
1794 add si, 16
1795 loop @B
1796 POPRF
1797 ENDIF
1798ENDIF
1799
1800 ; Restore registers
1801 pop es
1802 pop ds
1803 popa
1804
1805 ret
1806DriveIO_GatherDiskInfo EndP
1807
1808;------------------------------------------------------------------------------
1809; Scan all disks to gather information
1810;------------------------------------------------------------------------------
1811; IN : None
1812; OUT : CF=1 - some failure occured
1813; : ZF=1 - no harddisks
1814; NOTE : This does the preliminary gathering of disk information
1815;------------------------------------------------------------------------------
1816DriveIO_ScanDisks Proc Near
1817
1818IFDEF AUX_DEBUG
1819 IF 1
1820 DBG_TEXT_OUT_AUX 'DriveIO_ScanDisks:'
1821 PUSHRF
1822 call DEBUG_DumpRegisters
1823 ;~ call AuxIO_DumpParagraph
1824 ;~ call AuxIO_TeletypeNL
1825 POPRF
1826 ENDIF
1827ENDIF
1828
1829 ; Save all registers
1830 pusha
1831
1832 ; Get number of disks in DH
1833 call DriveIO_GetHardDriveCount
1834
1835 ; Check if there are any disks to scan
1836 xor cx, cx ; Prepare 16-bit counter
1837 mov cl, dh ; Number of disks now in CX
1838 jcxz DriveIO_ScanDisks_end ; Quit if no disks
1839
1840 ; Scan disks from 80h upward
1841 mov dl, 80h ; BIOS number of first disk
1842 DriveIO_ScanDisks_next:
1843 call DriveIO_GatherDiskInfo ; Gather info for this disk
1844 jc DriveIO_ScanDisks_end ; Quit if some error occured
1845 inc dl ; Advance to next disk
1846 loop DriveIO_ScanDisks_next ; Scan next disk if there is one
1847 test dl, dl ; Set ZF=0
1848 clc ; Indicate success
1849
1850 DriveIO_ScanDisks_end:
1851 ; Restore all registers
1852 popa
1853
1854 ret
1855DriveIO_ScanDisks EndP
1856
1857;------------------------------------------------------------------------------
1858; Calculate pointer to entry in DISKINFO structure
1859;------------------------------------------------------------------------------
1860; IN : DL BIOS disk number (80h etc)
1861; OUT : BX Pointer to entry
1862; NOTE : BIOS disk number must be valid
1863;------------------------------------------------------------------------------
1864DriveIO_CalcDiskInfoPointer Proc Near
1865 xchg bx, ax ; AX is used for calculation
1866 mov al, DISKINFO_Size ; Size of DISKINFO structure
1867 mov ah, dl ; BIOS disk number
1868 sub ah, 80h ; Now 0-based index
1869 mul ah ; Now offset into DISKINFO array
1870 add ax, offset [DiskInformation] ; Base of DISKINFO array
1871 xchg bx, ax ; BX now points to entry for disk
1872 ret
1873DriveIO_CalcDiskInfoPointer EndP
1874
1875;------------------------------------------------------------------------------
1876; Check if the BIOS disk number in DL is a harddisk and in range
1877;------------------------------------------------------------------------------
1878; IN : DL BIOS disk number (80h etc)
1879; OUT : CF=1 if invalid disk number or out of range
1880; NOTE : Only modifies flags
1881;------------------------------------------------------------------------------
1882DriveIO_IsValidHarddisk Proc Near Uses dx
1883 cmp dl, 80h ; BIOS disk number must be at least 80h
1884 jb @F ; Not a harddisk, exit with CY
1885 mov dh, dl ; Save to do compare
1886 sub dh, 80h ; Now 0 based disk number
1887 inc dh ; Now 1 based disk number
1888 cmp [TotalHarddiscs], dh ; Out of range, exit with CY
1889 @@: ret
1890DriveIO_IsValidHarddisk EndP
1891
1892
1893; Values for sectors per track table corresponding to DriveIO_IsHugeDrive return value.
1894;~ secs_per_track_table db 63,127,255,255,255,255
1895
1896;~ db_lmlvm db 'Load Master LVM -- disk: ',0
Note: See TracBrowser for help on using the repository browser.