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

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

Removed 'Force BIOS-LBA Usage' entry from AiR-BOOT SETUP [2012-05-15]

This commit eliminates the severe bug that previous commits warned
about in their commit-message. The cause of the bug is not handling
CHS values when modifying LVM-information. Thus, when LBA-access was
disabled, the CHS-access method was used with improper values. This
resulted in a CHS address of (0,0,1), which is the MBR, and then
erroneously writing the modified LVM-record to it.

While a freshly installed AiR-BOOT of v1.07 or higher defaults to having
LBA enabled, this is not the case for v1.06. Since AiR-BOOT merges the
previous configuration, any upgrade from v1.06 with LBA set to disabled
would propagate the setting to the new version. Modifying
LVM-information from the AiR-BOOT SETUP, like changing the label or
fiddling with drive-letter assignments, would then trigger the bug and
write the LVM-record to the MBR. Users fiddling with the SETUP could
also disable LBA-access and trigger the bug.

This commit removes the 'Force BIOS-LBA Usage' option from the
AiR-BOOT SETUP, preventing users to disable LBA. Also, when AiR-BOOT
starts, it now always enables LBA-addressing, so CHS-addressing is not
used anymore. Furthermore, the Installer is modified to always enable
LBA-addressing in the AiR-BOOT configuration it writes to disk.
This ensures that older versions, which do not implicitly enable LBA on
starting, will find LBA as enabled.

On today's systems there is no need to use CHS-addressing anymore.
In fact, it does more harm than good because the CHS values do not
represent true physical geometry anymore. Instead, the drive and
the BIOS do translations that can cause unpredictable results when
moving the drive between systems. This is particularly true for USB
mass storage devices.

Therefore, CHS-addressing will be removed from AiR-BOOT.
This will free-up badly needed code space and create some room in the
internal partition tables that can be put to other use.

Info

o Bug Description

Trashing the Master Boot Record.

o Cause

Not handling CHS values while modifying LVM-information.

o Effect

Writing the modified LVM-record to the MBR when modifying LVM
information from the AiR-BOOT SETUP.
(like the partition-label or drive-letter assignments)

o Measures

  • Remove 'Force BIOS-LBA Usage' from AiR-BOOT SETUP
  • Always enable LBA when AiR-BOOT starts
  • Always set LBA enabled when writing on-disk AiR-BOOT configuration

o Affected AiR-BOOT versions

*All* v1.0.8 pre-releases up and including commit [2012-05-13].

File size: 43.6 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 0 - 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 ;~ pusha
215 ;~ call AuxIO_TeletypeNL
216;~
217 ;~ ; LBA
218 ;~ xchg dx,bx
219 ;~ call AuxIO_TeletypeHexDWord
220 ;~ call AuxIO_TeletypeNL
221 ;~ xchg bx,dx
222;~
223 ;~ ; CYL
224 ;~ mov al,ch
225 ;~ call AuxIO_TeletypeHexByte
226 ;~ call AuxIO_TeletypeNL
227;~
228 ;~ ; HEAD
229 ;~ mov al,dh
230 ;~ call AuxIO_TeletypeHexByte
231 ;~ call AuxIO_TeletypeNL
232;~
233 ;~ ; SEC
234 ;~ mov al,cl
235 ;~ call AuxIO_TeletypeHexByte
236 ;~ call AuxIO_TeletypeNL
237;~
238 ;~ ; DRIVE
239 ;~ mov al,dl
240 ;~ call AuxIO_TeletypeHexByte
241 ;~ call AuxIO_TeletypeNL
242 ;~ popa
243;~
244 ;~ ;local ts:word
245 ;~ ;local ts2:word
246
247 pusha
248
249 ; Dump drive
250 ;mov si,offset drive
251 ;call AuxIO_Print
252 ;xchg al,dl
253 ;call AuxIO_TeletypeHexByte
254 ;call AuxIO_TeletypeNL
255 ;xchg dl,al
256
257 ; Dump SPT
258 ;mov si,offset spt_used
259 ;call AuxIO_Print
260 push dx
261 push bx
262 xor dh,dh
263 and dl,01111111b
264 shl dx,1
265 shl dx,1
266 mov bx, offset TrueSecs
267 add bx,dx
268 mov ax,word ptr [bx]
269 ;mov [ts],ax
270 ;call AuxIO_TeletypeHexWord
271 ;call AuxIO_TeletypeNL
272 pop bx
273 pop dx
274
275 pusha
276 push dx
277 ; Location of extended position
278 mov dx,word ptr [ExtendedAbsPos+02]
279 mov ax,word ptr [ExtendedAbsPos+00]
280 ;call AuxIO_TeletypeHexDWord
281 ;call AuxIO_TeletypeNL
282 pop dx
283
284 xor dh,dh
285 and dl,01111111b
286 shl dx,1
287 shl dx,1
288 mov bx, offset TrueSecs
289 add bx,dx
290
291 mov ax, word ptr[bx]
292 ;call AuxIO_TeletypeHexWord
293 ;call AuxIO_TeletypeNL
294 mov al,[ExtendedAbsPosSet] ; if true -> 1st sector of extpart (EBR), not logpart(BPB)
295 ;call AuxIO_TeletypeHexByte
296 ;call AuxIO_TeletypeNL
297 ;mov si,offset PartitionSector
298 ;call AuxIO_DumpSector
299 popa
300
301 ; LBA
302 ;mov si,offset before_lvm_adjust
303 ;call AuxIO_Print
304
305 ;xchg dx,bx
306 ;call AuxIO_TeletypeHexDWord
307 ;call AuxIO_TeletypeNL
308 ;xchg bx,dx
309 popa
310
311
312 ;or bx,ax
313 test byte ptr [ExtendedAbsPosSet],1
314 jz pri
315
316
317
318
319 ;pusha
320 ;mov si,offset before_lvm_adjust_log
321 ;call AuxIO_Print
322 ; LBA
323 ;xchg dx,bx
324 ;call AuxIO_TeletypeHexDWord
325 ;call AuxIO_TeletypeNL
326 ;xchg bx,dx
327 ;popa
328
329
330 push dx
331 push bx
332
333 xor dh,dh
334 and dl,01111111b
335 shl dx,1
336 shl dx,1
337 mov bx,offset TrueSecs
338 add bx,dx
339 mov dx,[bx]
340 dec dx
341 add ax,dx
342
343 pop bx
344 pop dx
345 adc bx,0
346
347
348 ;pusha
349 ;mov si,offset after_lvm_adjust_log
350 ;call AuxIO_Print
351 ; LBA
352 ;xchg dx,bx
353 ;call AuxIO_TeletypeHexDWord
354 ;call AuxIO_TeletypeNL
355 ;xchg bx,dx
356 ;popa
357
358 jmp done
359
360
361
362
363 pri:
364
365
366 push ax
367 push cx
368 xor ch, ch ; Zero out upper-byte
369
370 push dx
371 xor dh,dh
372 and dl,01111111b
373 shl dx,1
374 shl dx,1
375
376 push bx
377 mov bx,offset TrueSecs
378 add bx,dx
379 mov ax,[bx]
380 ;mov [ts2],ax
381 pop bx
382 pop dx
383
384
385
386 ;~ mov al, 63
387 ;~ call VideoIO_PrintByteDynamicNumber
388 ;~ self: jmp self
389
390
391
392 ; DEZE WERKT SOMS NIET GOED
393 ; ROMMELT MET CYLINDERS
394 ; ALLEEN TOEPASSEN ALS INT13X NIET ACTIEF !
395
396 and cl, al ; Isolate lower bits, because upper
397 mov ah, 0
398 mov si, ax ; ones may be used for cylinder
399 sub si, cx
400
401 pop cx
402 pop ax
403
404 or cl, al ; Set sector to last sector
405 add ax, si ; Adjust lower LBA
406 adc bx, 0 ; Adjust LBA Sector (BX:AX)
407
408
409
410 ;~ push ax
411 ;~ call AuxIO_TeletypeHexWord
412 ;~ call AuxIO_TeletypeNL
413 ;~ mov ax,[ts]
414 ;~ call AuxIO_TeletypeHexWord
415 ;~ call AuxIO_TeletypeNL
416 ;~ mov ax,[ts2]
417 ;~ call AuxIO_TeletypeHexWord
418 ;~ call AuxIO_TeletypeNL
419 ;~ pop ax
420
421 ;~ and ax,[ts]
422
423 jmp done
424
425
426
427 done:
428
429 ;pusha
430 ;mov si,offset after_lvm_adjust
431 ;~ call AuxIO_Print
432 ; LBA
433 ;xchg dx,bx
434 ;~ call AuxIO_TeletypeHexDWord
435 ;~ call AuxIO_TeletypeNL
436 ;xchg bx,dx
437 ;popa
438
439 ;~ pusha
440 ;~ call AuxIO_TeletypeNL
441;~
442 ;~ ; CYL
443 ;~ mov al,ch
444 ;~ call AuxIO_TeletypeHexByte
445 ;~ call AuxIO_TeletypeNL
446;~
447 ;~ ; HEAD
448 ;~ mov al,dh
449 ;~ call AuxIO_TeletypeHexByte
450 ;~ call AuxIO_TeletypeNL
451;~
452 ;~ ; SEC
453 ;~ mov al,cl
454 ;~ call AuxIO_TeletypeHexByte
455 ;~ call AuxIO_TeletypeNL
456;~
457 ;~ ; DRIVE
458 ;~ mov al,dl
459 ;~ call AuxIO_TeletypeHexByte
460 ;~ call AuxIO_TeletypeNL
461 ;~ popa
462
463 ret
464DriveIO_LVMAdjustToInfoSector EndP
465
466
467
468
469
470
471; #########################################################################
472; Routine: Loads partition to ExecBase and checks for validity
473; #########################################################################
474; Calling : bx:ax - Absolute sector
475; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
476; Returns : Carry Set if invalid partition encountered
477; Preserve: all registers
478; #########################################################################
479DriveIO_LoadPartition Proc Near Uses si
480 mov wptr cs:[CurPartition_Location+0], ax
481 mov wptr cs:[CurPartition_Location+2], bx
482 mov wptr cs:[CurPartition_Location+4], dx
483 mov wptr cs:[CurPartition_Location+6], cx ; Saves the location
484 mov si, offset PartitionSector ; DS:SI - ExecBase
485 call DriveIO_LoadSector
486 clc
487 cmp wptr [si+LocBR_Magic], 0AA55h
488 je DIOLP_Success
489 ; We check, if we are scanning partitions. In that case, if CHS is not 0/0/1
490 ; we will display a "bad partition table" message and halt the system.
491 cmp cx, 0001h
492 jne DIOLP_Failed
493 or dh, dh
494 jnz DIOLP_Failed
495 stc ; Set carry, so no partition table
496 DIOLP_Success:
497
498 IFDEF AUX_DEBUG
499 ; show current partition location
500 ;~ pushf
501 ;~ pusha
502 ;~ call AuxIO_TeletypeNL
503 ;~ mov si,offset db_curpartloc
504 ;~ call AuxIO_Print
505 ;~ mov dx,word ptr [CurPartition_Location+02]
506 ;~ mov ax,word ptr [CurPartition_Location+00]
507 ;~ call AuxIO_TeletypeHexDWord
508 ;~ call AuxIO_TeletypeNL
509 ;~ mov si,offset PartitionSector
510 ;~ call AuxIO_DumpSector
511 ;~ call AuxIO_TeletypeNL
512 ;~ popa
513 ;~ popf
514 ENDIF
515
516 ret
517 DIOLP_Failed:
518 jmp DriveIO_GotLoadError
519DriveIO_LoadPartition EndP
520
521; #########################################################################
522; Routine: Writes a partition from ExecBase to its original sector
523; #########################################################################
524; Calling : none
525; Returns : none
526; Preserve: all registers
527; #########################################################################
528DriveIO_SavePartition Proc Near Uses ax bx cx dx si
529 mov ax, wptr cs:[CurPartition_Location+0]
530 mov bx, wptr cs:[CurPartition_Location+2]
531 mov dx, wptr cs:[CurPartition_Location+4]
532 mov cx, wptr cs:[CurPartition_Location+6] ; Gets prev. saved location
533 mov si, offset PartitionSector ; DS:SI - ExecBase
534 cmp wptr [si+LocBR_Magic], 0AA55h ; Checks for signature, if not found
535 jne DIOSP_SevereError ; we assume a really bad error
536 call DriveIO_SaveSector
537 DIOSP_SevereError:
538 ret
539DriveIO_SavePartition EndP
540
541; Keeps DS:SI for caller
542DriveIO_LoadTmpSector Proc Near
543 mov si, offset TmpSector
544 call DriveIO_LoadSector
545 ret
546DriveIO_LoadTmpSector EndP
547
548; Keeps DS:SI for caller
549DriveIO_SaveTmpSector Proc Near
550 mov si, offset TmpSector
551 call DriveIO_SaveSector
552 ret
553DriveIO_SaveTmpSector EndP
554
555; Keeps DS:SI for caller, sets carry if valid LVM sector encountered
556DriveIO_LoadLVMSector Proc Near Uses ax bx cx dx
557 test byte ptr [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
558 jnz DIOLLVMS_NoLVMSector ; don't load but declare as bad!
559 mov ax, wptr cs:[CurPartition_Location+0]
560 mov bx, wptr cs:[CurPartition_Location+2]
561 mov dx, wptr cs:[CurPartition_Location+4]
562 mov cx, wptr cs:[CurPartition_Location+6] ; Gets cur. partition location
563
564 call DriveIO_LVMAdjustToInfoSector
565
566 mov si, offset LVMSector
567 call DriveIO_LoadSector
568
569 IFDEF AUX_DEBUG
570 ; show current partition location
571 ;~ pushf
572 ;~ pusha
573 ;~ call AuxIO_TeletypeNL
574 ;~ mov si,offset db_curlvmsec
575 ;~ call AuxIO_Print
576 ;~ mov dx,bx
577 ;~ call AuxIO_TeletypeHexDWord
578 ;~ call AuxIO_TeletypeNL
579 ;~ mov si,offset LVMSector
580 ;~ call AuxIO_DumpSector
581 ;~ call AuxIO_TeletypeNL
582 ;~ popa
583 ;~ popf
584 ENDIF
585
586 call LVM_CheckSectorSignature
587 jnc DIOLLVMS_NoLVMSector
588 call LVM_CheckSectorCRC
589 jnc DIOLLVMS_NoLVMSector
590 ret
591 ; This here is called, if an invalid (or no) LVM information sector is found
592 ; It will truncate the first byte of the sector, so all other routines
593 ; will notice it easily by just comparing the first byte.
594 DIOLLVMS_NoLVMSector:
595 mov bptr [si+LocLVM_SignatureStart], 0
596 ret
597DriveIO_LoadLVMSector EndP
598
599; Keeps DS:SI for caller, saves at anytime w/o checks (!)
600DriveIO_SaveLVMSector Proc Near Uses ax bx cx dx
601 test byte ptr [CFG_IgnoreLVM], 1 ; We are supposed to ignore LVM, so
602 jnz DIOSLVMS_SevereError ; don't save at anytime (security!)
603 mov ax, wptr cs:[CurPartition_Location+0]
604 mov bx, wptr cs:[CurPartition_Location+2]
605 mov dx, wptr cs:[CurPartition_Location+4]
606 mov cx, wptr cs:[CurPartition_Location+6] ; Gets cur. partition location
607 call LVM_CheckSectorSignature
608 jnc DIOSLVMS_SevereError ; LVM Signature must be there
609
610IFDEF AUX_DEBUG
611 ;~ call DEBUG_DumpRegisters
612ENDIF
613
614 call DriveIO_LVMAdjustToInfoSector
615
616IFDEF AUX_DEBUG
617 ;~ call DEBUG_DumpRegisters
618ENDIF
619
620 mov si, offset LVMSector
621 call DriveIO_SaveSector
622 DIOSLVMS_SevereError:
623 ret
624DriveIO_SaveLVMSector EndP
625
626; Rousseau: Move this to BSS and merge with int13xbuf there.
627
628; Memory-Block that holds information for LBA-access via INT 13h
629DriveIO_DAP db 10h ; Size of paket
630 db 0 ; Reserved
631DriveIO_DAP_NumBlocks dw 0 ; Number of blocks
632DriveIO_DAP_Transfer dd 0 ; Transfer Adress
633DriveIO_DAP_Absolute dd 0 ; Absolute Sector
634 dd 0 ; Second Part of QWORD
635
636; Special error message instead of "LOAD ERROR" during partition scanning,
637; so users will notice that something is bad with their partition table(s)
638DriveIO_GotLoadError Proc Near
639 test byte ptr cs:[CurIO_Scanning], 1 ; Must be CS:, cause DS!=CS maybe here
640 jnz InScanMode
641 jmp MBR_LoadError
642 InScanMode:
643 mov si, offset TXT_BrokenPartitionTable
644 push cs
645 pop ds
646 call MBR_Teletype
647 mov si, offset BrokenHDD
648 sub dl, 50h ; 80h -> '0'
649 cmp dl, 39h
650 jbe DIOGLE_BelowA
651 add dl, 7 ; 3Ah -> 'A'
652 DIOGLE_BelowA:
653 mov bptr [si+5], dl
654 call MBR_Teletype
655
656 ; JWasm: cannot jump to local label in other procedure.
657 ; Changed to halt here.
658 ;jmp MBRLE_Halt
659 DriveIO_GotLoadError_halt:
660 jmp DriveIO_GotLoadError_halt
661DriveIO_GotLoadError EndP
662
663; #########################################################################
664; Routine: Loads a specified sector to DS:DI
665; #########################################################################
666; Calling : bx:ax - Absolute sector
667; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
668; ds:si - Destination-Adress
669; Returns : none
670; Preserve: all registers
671; #########################################################################
672DriveIO_LoadSector Proc Near Uses ax bx ds si es di
673 ; Is the drive not a harddrive?
674 cmp dl, 80h
675 jb DIOLS_UseNormal
676
677 test byte ptr cs:[CurIO_UseExtension], 1
678 jz DIOLS_UseNormal
679 ; Are we forced do use LBA via Setting?
680 jnz DIOLS_UseExtension
681
682 ; Upper 8 bits of LBA-address set? -> Use LBA (maximum boundary is FB0400h)
683 or bh, bh
684 jnz DIOLS_UseExtension
685 ; Compare Switch-Table value to bit 16-23 of LBA-address
686 mov di, dx
687 and di, 007Fh
688 cmp bptr cs:[LBASwitchTable+di], bl
689 jbe DIOLS_UseExtension
690 DIOLS_UseNormal:
691 mov di, 3
692 DIOLS_ErrorLoop:
693 push ds
694 pop es
695 mov bx, si ; ES:BX - Destination
696 mov ax, 0201h ; Function 2 - Load Sector
697 int 13h
698 jnc DIOLS_Success
699 dec di
700 jnz DIOLS_ErrorLoop
701 ; Sector load failed...
702 jmp DriveIO_GotLoadError
703
704 DIOLS_UseExtension:
705 push cx
706 mov cs:[DriveIO_DAP_NumBlocks], 1 ; Copy ONE sector
707 mov wptr cs:[DriveIO_DAP_Transfer+0], si
708 mov cx, ds
709 mov wptr cs:[DriveIO_DAP_Transfer+2], cx ; Fill out Transfer Adress
710 mov wptr cs:[DriveIO_DAP_Absolute+0], ax
711 mov wptr cs:[DriveIO_DAP_Absolute+2], bx ; Fill out Absolute Sector
712 push cs
713 pop ds
714 mov si, offset DriveIO_DAP
715 mov ah, 42h ; Extended Read
716 int 13h
717 pop cx
718 jnc DIOLS_Success
719 ; Sector load failed...
720 jmp DriveIO_GotLoadError
721
722 DIOLS_Success:
723 ret
724DriveIO_LoadSector EndP
725
726
727
728;
729; ############################################################
730; # Load a specified sector from a disk using LBA addressing #
731; ############################################################
732;
733; In
734; --
735; DL = Physical Disk
736; BX:CX = LBA sector
737; DI:SI = Target buffer
738;
739; Out
740; ---
741; AX = Error code
742;
743DriveIO_LoadSectorLBA Proc Near Uses bx cx dx si di ds es
744 ; Get one sector
745 mov cs:[DriveIO_DAP_NumBlocks], 1
746
747 ; Setup buffer address
748 mov wptr cs:[DriveIO_DAP_Transfer+0], si
749 mov wptr cs:[DriveIO_DAP_Transfer+2], di
750
751 ; Setup LBA address of requested sector
752 mov wptr cs:[DriveIO_DAP_Absolute+0], cx
753 mov wptr cs:[DriveIO_DAP_Absolute+2], bx
754 mov wptr cs:[DriveIO_DAP_Absolute+4], 0
755 mov wptr cs:[DriveIO_DAP_Absolute+6], 0
756
757 ; Address of packet
758 mov si, offset DriveIO_DAP
759
760 ; Do the extended read
761 mov ah, 42h
762 int 13h
763
764 ; Looking good so far
765 jnc DriveIO_LoadSectorLBA_succes1
766
767 ; AH should not be zero, if it is then set to undefined and set carry
768 test ah,ah
769 jnz DriveIO_LoadSectorLBA_error1
770 mov ah, 0bbh ; Undefined error
771 DriveIO_LoadSectorLBA_error1:
772 stc
773 jmp DriveIO_LoadSectorLBA_exit
774
775 ; AL should be zero, if not then set to undefined and set carry
776 DriveIO_LoadSectorLBA_succes1:
777 test ah,ah
778 jz DriveIO_LoadSectorLBA_exit
779 stc
780 jmp DriveIO_LoadSectorLBA_exit
781
782 ; Return to caller
783 DriveIO_LoadSectorLBA_exit:
784 ret
785DriveIO_LoadSectorLBA EndP
786
787
788
789
790; #########################################################################
791; Routine: Writes DS:SI to a specified sector
792; #########################################################################
793; Calling : bx:ax - Absolute sector
794; cx:dx - Cylinder/Sector, Side/Drive (hi/lo-byte)
795; ds:si - Source-Adress
796; Returns : none
797; Preserve: all registers
798; #########################################################################
799DriveIO_SaveSector Proc Near Uses ax bx cx ds si es di
800
801IFDEF AUX_DEBUG
802 call DEBUG_DumpRegisters
803 call AuxIO_DumpSector
804 call AuxIO_TeletypeNL
805ENDIF
806
807 test byte ptr cs:[CurIO_UseExtension], 1
808 jz DIOSS_UseNormal
809 ; Are we forced do use LBA via Setting?
810 ; Always use INT13X on v1.0.8.
811 ;~ test byte ptr cs:[CFG_ForceLBAUsage], 1
812 ;~ jnz DIOSS_UseExtension
813 jmp DIOSS_UseExtension
814 ; Is the drive not a harddrive?
815 cmp dl, 80h
816 jb DIOSS_UseNormal
817 ; Upper 8 bits of LBA-address set? -> Use LBA (maximum boundary is FB0400h)
818 or bh, bh
819 jnz DIOSS_UseExtension
820 ; Compare Switch-Table value to bit 16-23 of LBA-address
821 mov di, dx
822 and di, 007Fh
823 cmp bptr cs:[LBASwitchTable+di], bl
824 jbe DIOSS_UseExtension
825 DIOSS_UseNormal:
826 mov di, 3
827 DIOSS_ErrorLoop:
828 push ds
829 pop es
830 mov bx, si ; ES:BX - Destination
831 mov ax, 0301h ; Function 3 - Write Sector
832 int 13h
833 jnc DIOSS_Success
834 dec di
835 jnz DIOSS_ErrorLoop
836 call MBR_SaveError
837
838 DIOSS_UseExtension:
839 push cx
840 mov cs:[DriveIO_DAP_NumBlocks], 1 ; Copy ONE sector
841 mov wptr cs:[DriveIO_DAP_Transfer+0], si
842 mov cx, ds
843 mov wptr cs:[DriveIO_DAP_Transfer+2], cx ; Fill out Transfer Adress
844 mov wptr cs:[DriveIO_DAP_Absolute+0], ax
845 mov wptr cs:[DriveIO_DAP_Absolute+2], bx ; Fill out Absolute Sector
846 push cs
847 pop ds
848 mov si, offset DriveIO_DAP
849 mov ax, 4300h ; Extended Write (No Verify)
850 int 13h
851 pop cx
852 jnc DIOSS_Success
853 call MBR_SaveError
854
855 DIOSS_Success:
856 ret
857DriveIO_SaveSector EndP
858
859
860; See if a LVM-sector is valid.
861; In : si, pointer to sector
862; Out : CY if valid LVM sector, NC if not
863DriveIO_LVMSectorValid Proc Near
864 pusha
865
866 call LVM_CheckSectorSignature
867 ; NC if no signature found
868 jnc DriveIO_LVMSectorValid_End
869
870 call LVM_CheckSectorCRC
871 ; Force valid !!!
872 stc
873
874 DriveIO_LVMSectorValid_End:
875 popa
876 ret
877DriveIO_LVMSectorValid EndP
878
879; ------------------------------------------------------
880; Rousseau: # Load the master LVM-sector if one exists #
881; ------------------------------------------------------
882; Load the master LVM-sector to get the number of sectors per track as eCS views the drive.
883; If no master LVM-sector is found it is assumed eCS is not installed.
884; The master LVM-sector can be located at three different places according to drive size
885; and partitioning scheme and driver used.
886; When DANIS506.ADD is used, the eCS extended geometry will be 255/127 for drives >502GiB but <1TiB.
887; Then the location will be sector 127 which is LBA 126 (7Eh).
888; IBM1S506.ADD will always use 255/255 for the extended eCS geometry.
889; DANIS506.ADD will use 255/255 for drives >1TiB.
890; Then the location of the master LVM-sector will be 255 which is LBA 254 (FEh).
891; When eCS is installed on a huge drive that alread had a system on it, eCS will be confined to the
892; lower 502GiB of the drive. In this case the normal geometry from Int13X will be used.
893; This is also the case when no valid master LVM-sector can be found.
894;
895; Return CF when valid master LVM sector found, NC if not.
896; Loads sector at [LVMSector] !
897DriveIO_LoadMasterLVMSector Proc Near
898 pusha
899
900 ;~ mov si,offset db_lmlvm
901 ;~ call AuxIO_Print
902
903 ;~ ; Physical disk
904 ;~ mov al,'<'
905 ;~ call VideoIO_PrintSingleChar
906 ;~ mov al,dl
907 ;~ call VideoIO_PrintHexByte
908 ;~ mov al,'>'
909 ;~ call VideoIO_PrintSingleChar
910;~
911 ;~ call AuxIO_TeletypeHexByte
912 ;~ call AuxIO_TeletypeNL
913
914
915 ; Loop over the sector-translation table,
916 ; process the first three values from high (255) to low (bios spt, most likely 63)
917 mov cx,3
918 DriveIO_LoadMasterLVMSector_NextTry:
919 ; Number of sectors to read
920 mov [DriveIO_DAP_NumBlocks],1
921
922 ; Setup destination address
923 mov si, offset LVMSector
924 mov wptr [DriveIO_DAP_Transfer+0],si
925 mov ax, ds
926 mov wptr [DriveIO_DAP_Transfer+2],ax
927
928 ; Get the sector-number of the next possible LVM sector (255,127,63)
929 ; using the translation table and the counter as the index
930 mov bx,offset secs_per_track_table
931 mov ax,cx
932 dec ax
933 xlatb
934 dec al
935
936 ;
937 ; AX now contains the LBA address of the sector
938 ; that could be an LVM sector.
939 ; This is all in track0 so the address will not exceed 64kiB sectors.
940 ;
941
942 ;~ push ax
943 ;~ push ax
944 ;~ mov al,'$'
945 ;~ call VideoIO_PrintSingleChar
946 ;~ pop ax
947 ;~ call VideoIO_PrintHexByte
948 ;~ mov al,'$'
949 ;~ call VideoIO_PrintSingleChar
950 ;~ pop ax
951
952IFDEF AUX_DEBUG
953 ; Dump the value
954 ;~ call AuxIO_TeletypeHexByte
955 ;~ call AuxIO_TeletypeNL
956ENDIF
957
958 ; Setup the requested LBA sector number
959 mov wptr [DriveIO_DAP_Absolute+0],ax ; LBA low
960 mov wptr [DriveIO_DAP_Absolute+2],00h ; LBA high
961 mov si, offset DriveIO_DAP ; address request packet
962 mov ah, 42h
963 int 13h ; do the i/o
964 cmc ; Complement carry so we can exit imm. on error
965 jnc DriveIO_LoadMasterLVMSector_End ; oops, return with NC
966
967
968 mov si,offset LVMSector
969
970 ; See if this is a valid LVM-sector
971 call DriveIO_LVMSectorValid
972
973; pushf
974; mov ah,0
975; rcl ah,1
976; mov al,'|'
977; call VideoIO_PrintSingleChar
978; mov al,ah
979; call VideoIO_PrintHexByte
980; mov al,'|'
981; call VideoIO_PrintSingleChar
982; popf
983
984
985 ; Yep, we found the master LVM-sector
986 jc DriveIO_LoadMasterLVMSector_Found
987 ; Try next location
988 loop DriveIO_LoadMasterLVMSector_NextTry
989
990 ; No master LVM-sector found, set CF=false
991 clc
992
993 DriveIO_LoadMasterLVMSector_Found:
994 DriveIO_LoadMasterLVMSector_End:
995 popa
996 ret
997DriveIO_LoadMasterLVMSector Endp
998
999
1000
1001
1002; ---------------------------------------------------
1003; Rousseau ## Large drives, (eCS) geometry and LBA ##
1004; ---------------------------------------------------
1005; A sector size of 512 bytes is assumed in the below calculations.
1006; Note that this scheme changes when the sector size will be 4096 or larger,
1007; like with modern drives that do not translate to 512 bytes per sector anymore.
1008; These drives will have a capacity above the 2TiB LBA32 boundary.
1009; For now, we assume drives <=2TiB with a sector size of 512 bytes.
1010
1011; There are a few boundaries that are of importance.
1012; Note that these are disk-boundaries and not partition boundaries.
1013; Even with a small partition, like <502GiB, OS/2 will use extended geometry on an
1014; empty huge disk.
1015; These boundaries are (from high to low):
1016
1017; (code 5)
1018; 2^32 = 4294967296 = 100000000 sectors = 2048 GiB
1019; This is the LBA32 2TiB boundary.
1020; Everything above it must be addressed using LBA48.
1021; OS/2 can currently not address this space above.
1022
1023; (code4)
1024; 65536*255*255 = 4261478400 = FE010000 sectors ~ 2032 GiB
1025; This is the max OS/2 boundary using 255/255 extended geometry.
1026; OS/2 can currently not address this space above.
1027
1028; (code 3)
1029; 2^31 = 2147483648 = 80000000 sectors = 1024 GiB
1030; This is the LBA32 1TiB boundary.
1031; OS/2 can address this space and will use 255/255 extended geometry.
1032
1033; (code 2)
1034; 65536*255*127 = 2122383360 = 7E810000 sectors ~ 1012 GiB
1035; This is the DANI 1TiB boundary.
1036; OS/2 can address this space and will use 255/255 extended geometry.
1037; Below this DANI will use 255/127 extended geometry.
1038; This matters on where the LVM-sectors are located !
1039
1040; (code 1)
1041; 65536*255*63 = 1052835840 = 3EC10000 sectors ~ 502 GiB
1042; This is the current OS/2 limit using this geometry because OS/2 can currently
1043; not address more than 65536 cylinders.
1044; DANI will address space above with 255/127 extended geometry up until the DANI 1TiB boundary (code 2)
1045
1046; (code 0)
1047; Everything below 65536*255*63 will be addressed using standard geometry.
1048
1049
1050;
1051; This function will return the following values:
1052;
1053
1054; 5 = This drive is above the 2^32 LBA32 (2TB) boundary and has more than 4294967296 sectors.
1055; LBA48 addressing is needed to access the complete capacity of the drive.
1056; OS/2 is currently unable to do so.
1057
1058; 4 = This drive is above the 65536*255*255 (4261478400) boundary but below 2^32.
1059; This is an OS/2 boundary and OS/2 is not able to access the drive above this boundary.
1060
1061; 3 = This drive is above the 2^31 (1TB) boundary and has more than 2147483648 sectors.
1062; OS/2 is able to access the drive using it's extended geometry.
1063; Both DANIS506 and IBM1S506 will use the 255/255 scheme.
1064
1065; 2 = This drive is above the 65536*255*127 (2122383360) boundary but below 2^31.
1066; OS/2 is able to access the drive using it's extended geometry.
1067; Both DANIS506 and IBM1S506 will use the 255/255 scheme.
1068
1069; 1 = This drive is above the 65536*255*63 (1052835840) boundary but below 65536*255*127.
1070; OS/2 is able to access the drive using it's extended geometry.
1071; Note that DANIS506 will use 255/127 and IBM1S506 will use 255/255 geometry !
1072; Using DANI or IBM influences the location of the LVM info-sectors !
1073
1074; 0 = This drive is below the 65536*255*63 (1052835840) boundary.
1075; OS/2 is able to access this drive using the standard 255/63 geometry.
1076
1077; So, any return value >0 means OS/2 extended geometry will be used.
1078; Value 1 will use 255/127 with DANIS506 but 255/255 with IBM1S506.
1079; Values 2 and 3 will use 255/255 on both drivers.
1080; You can or with 0x01 and check for 3 in this case.
1081; Any value above 3 will be a drive who's capacity cannot be fully used by OS/2
1082; The upper limit of 65536*255*255 will be in effect here.
1083
1084; Note this function currently handles the boot-drive only !
1085; It should be extended and use dl for the drive-number as a parameter.
1086; Because we use this function to get this info in a number of places,
1087; all regs and flags except AX are saved and restored.
1088
1089; DL contains BIOS disk-number; 80h for first, 81h for second, etc.
1090DriveIO_GatherDiskInfo Proc Near
1091 pushf
1092 push bx
1093 push cx
1094 push dx
1095 push si
1096 push di
1097 push es
1098
1099 ; Set ES to CS for buffer clearing
1100 push cs
1101 pop es
1102
1103 ; Clear the buffer
1104 ; Also setup the buffer size.
1105 ; Old Phoenix BIOSses require word (flags) at 02 to be zero,
1106 ; so we clear the whole buffer to be sure.
1107 mov cx, i13xbuf_size ; Dynamically calculated by assembler.
1108 mov di, offset i13xbuf ; Points to size field.
1109 mov [di],cx ; Setup buffer-size.
1110 inc di
1111 inc di ; Now pointing at actual buffer.
1112 xor ah,ah ; Fill value.
1113 cld ; Direction up.
1114 rep stosb ; Clear buffer.
1115
1116 ; Get the drive parameters
1117 mov ah, 48h ; Get Drive Parameters (extended version)
1118 ;mov dl, 80h ; Drive number
1119 mov si, offset i13xbuf ; Buffer for result-info
1120 push dx
1121 int 13h ; Call the BIOS-function
1122 pop dx
1123
1124 ; Do some error-checking
1125 or ah,ah ; AH is zero if no error (ZF=1 if no error)
1126 mov ax,0 ; Setup code for non-huge drive (does not influence ZF)
1127 jz DriveIO_GatherDiskInfo_ok ; Return if error (AL<>0 thus ZF=0) but CY not set, assuming non-huge drive
1128 jnc DriveIO_GatherDiskInfo_ok ; Return if error (CY=1), assuming non-huge drive
1129 jmp DriveIO_GatherDiskInfo_ret
1130
1131
1132 DriveIO_GatherDiskInfo_ok:
1133
1134 ;
1135 ; Store the drive geometry
1136 ;
1137
1138 mov si, offset i13xbuf
1139
1140 xor dh,dh
1141 and dl,01111111b
1142 shl dx,1
1143 shl dx,1
1144
1145 ; Store number of cylinders on disk
1146 mov bx, offset BIOS_Cyls
1147 add bx,dx
1148 mov ax,[si+04h]
1149
1150 mov word ptr [bx+00],ax
1151 mov ax,[si+06]
1152 mov word ptr [bx+02],ax
1153
1154 ; Store number of heads per cylinder
1155 mov bx, offset BIOS_Heads
1156 add bx,dx
1157 mov ax,[si+08h]
1158 mov word ptr [bx+00],ax
1159 mov ax,[si+0ah]
1160 mov word ptr [bx+02],ax
1161
1162 ; Store number of sectors per track
1163 mov bx, offset BIOS_Secs
1164 add bx,dx
1165 mov ax,[si+0ch]
1166 mov word ptr [bx+00],ax
1167
1168 ; Update first byte of translation-table to conform to BIOS SPT
1169 mov byte ptr [secs_per_track_table], al
1170
1171 mov ax,[si+0eh]
1172 mov word ptr [bx+02],ax
1173
1174 ; Store total secs
1175 mov bx, offset BIOS_TotalSecs
1176 add bx,dx
1177 add bx,dx
1178 mov ax,[si+10h]
1179
1180 mov word ptr [bx+00],ax
1181 mov ax,[si+12h]
1182 mov word ptr [bx+02],ax
1183 mov ax,[si+14h]
1184 mov word ptr [bx+04],ax
1185 mov ax,[si+18h]
1186 mov word ptr [bx+06],ax
1187
1188 ; Store number of bytes per sector
1189 mov bx, offset BIOS_Bytes
1190 add bx,dx
1191 mov ax,[si+18h]
1192 mov [bx],ax
1193
1194
1195 ;
1196 ; See of it's a huge drive of not
1197 ;
1198
1199 ; Drive is larger than 2TiB
1200 mov ax,5 ; Drive code (5)
1201 mov bx, [si+14h] ; Low word of high dword of sector-count
1202 or bx, [si+16h] ; High word of high dword of sector-count
1203 jnz DriveIO_GatherDiskInfo_ret ; If non-zero we have a drive with >2^32 sectors and thus LBA48 addressing
1204
1205 ; Drive is larger than max OS/2 capacity
1206 dec ax ; Drive code (4)
1207 mov bx, [si+12h] ; High word of low dword of sector-count
1208 cmp bx, 0fe01h ; Boundary
1209 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1210 ; we have a drive larger than to 65536*255*255 = FE010000 sectors
1211
1212 ; Drive can be completely utilized by OS/2
1213 dec ax ; Drive code (3)
1214 cmp bx, 8000h ; Boundary
1215 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1216 ; we have a drive larger than 2^31 sectors but smaller than 65536*255*255
1217
1218 ; This is the small area between DANI 1TiB and LBA 1TiB
1219 dec ax ; Drive code (2)
1220 cmp bx, 7e81h ; Boundary
1221 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1222 ; we have a drive larger than 65536*255*127 but <65536*255*255
1223 ; DANIS506.ADD will use 255/255 extended geometry
1224
1225 ; DANI will use 255/127 in this area, this could impact the location of LVM-sectors ! (last sec on track)
1226 dec ax ; Drive code (1)
1227 cmp bx, 3ec1h ; Boundary
1228 jae DriveIO_GatherDiskInfo_ret ; If above or equal to boundary,
1229 ; we have a drive larger than 65536*255*63 sectors (OS/2 502GiB Limit!)
1230 ; DANIS506.ADD will use 255/127 extended geometry !
1231 ; IBM1S506.ADD will use 255/255 extended geometry !
1232
1233 ; We have a drive that can be addressed using standard 255/63 geometry
1234 dec ax ; Drive code (0)
1235 ; We have a drive smaller than 65536*255*63 = 3EC10000 sectors
1236
1237 DriveIO_GatherDiskInfo_ret:
1238 pop es
1239 pop di
1240 pop si
1241 pop dx
1242 pop cx
1243 pop bx
1244
1245 mov byte ptr [CurIO_UseExtension],1
1246
1247 popf
1248 ret
1249DriveIO_GatherDiskInfo EndP
1250
1251
1252
1253; Values for sectors per track table corresponding to DriveIO_IsHugeDrive return value.
1254secs_per_track_table db 63,127,255,255,255,255
1255
1256;db_lmlvm: db 'Load Master LVM -- disk: ',0
Note: See TracBrowser for help on using the repository browser.