Changeset 137


Ignore:
Timestamp:
Apr 8, 2017, 12:27:34 AM (8 years ago)
Author:
Ben Rietbroek
Message:

Reimplemented the gathering of disk information [v1.1.1-testing]

The new method now uses the DISKINFO structure to store all relevant
information about the attached disks. This gets rid of the many faulty
assumptions and scattered storage locations.

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:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/bootcode/regular/driveio.asm

    r136 r137  
    14531453
    14541454
    1455 
    1456 ; ---------------------------------------------------
    1457 ; Rousseau ## Large drives, (OS/2) geometry and LBA ##
    1458 ; ---------------------------------------------------
    1459 ; A sector size of 512 bytes is assumed in the below calculations.
    1460 ; Note that this scheme changes when the sector size will be 4096 or larger,
    1461 ; like with modern drives that do not translate to 512 bytes per sector anymore.
    1462 ; These drives will have a capacity above the 2TiB LBA32 boundary.
    1463 ; For now, we assume drives <=2TiB with a sector size of 512 bytes.
    1464 
    1465 ; There are a few boundaries that are of importance.
    1466 ; Note that these are disk-boundaries and not partition boundaries.
    1467 ; Even with a small partition, like <502GiB, OS/2 will use extended geometry on
    1468 ; an empty huge disk.
    1469 ; These boundaries are (from high to low):
    1470 
    1471 ; (code 5)
    1472 ; 2^32 = 4294967296 = 100000000 sectors = 2048 GiB
    1473 ;   This is the LBA32 2TiB boundary.
    1474 ;   Everything above it must be addressed using LBA48.
    1475 ;   OS/2 can currently not address this space above.
    1476 
    1477 ; (code4)
    1478 ; 65536*255*255 = 4261478400 = FE010000 sectors ~ 2032 GiB
    1479 ;   This is the max OS/2 boundary using 255/255 extended geometry.
    1480 ;   OS/2 can currently not address this space above.
    1481 
    1482 ; (code 3)
    1483 ; 2^31 = 2147483648 = 80000000 sectors = 1024 GiB
    1484 ;   This is the LBA32 1TiB boundary.
    1485 ;   OS/2 can address this space and will use 255/255 extended geometry.
    1486 
    1487 ; (code 2)
    1488 ; 65536*255*127 = 2122383360 = 7E810000 sectors ~ 1012 GiB
    1489 ;   This is the DANI 1TiB boundary.
    1490 ;   OS/2 can address this space and will use 255/255 extended geometry.
    1491 ;   Below this DANI will use 255/127 extended geometry.
    1492 ;   This matters on where the LVM-sectors are located !
    1493 
    1494 ; (code 1)
    1495 ; 65536*255*63  = 1052835840 = 3EC10000 sectors ~ 502 GiB
    1496 ;   This is the current OS/2 limit using this geometry because OS/2 can
    1497 ;   currently not address more than 65536 cylinders.
    1498 ;   DANI will address space above with 255/127 extended geometry up until
    1499 ;   the DANI 1TiB boundary (code 2)
    1500 
    1501 ; (code 0)
    1502 ; Everything below 65536*255*63 will be addressed using standard geometry.
    1503 
    1504 
    1505 ;
    1506 ; This function will return the following values:
    1507 ;
    1508 
    1509 ; 5 = This drive is above the 2^32 LBA32 (2TB) boundary and has more
    1510 ;     than 4294967296 sectors.
    1511 ;     LBA48 addressing is needed to access the complete capacity of the drive.
    1512 ;     OS/2 is currently unable to do so.
    1513 
    1514 ; 4 = This drive is above the 65536*255*255 (4261478400) boundary but below 2^32.
    1515 ;     This is an OS/2 boundary and OS/2 is not able to access the drive above
    1516 ;     this boundary.
    1517 
    1518 ; 3 = This drive is above the 2^31 (1TB) boundary and has more than
    1519 ;     2147483648 sectors.
    1520 ;     OS/2 is able to access the drive using it's extended geometry.
    1521 ;     Both DANIS506 and IBM1S506 will use the 255/255 scheme.
    1522 
    1523 ; 2 = This drive is above the 65536*255*127 (2122383360) boundary but below 2^31.
    1524 ;     OS/2 is able to access the drive using it's extended geometry.
    1525 ;     Both DANIS506 and IBM1S506 will use the 255/255 scheme.
    1526 
    1527 ; 1 = This drive is above the 65536*255*63 (1052835840) boundary but
    1528 ;     below 65536*255*127.
    1529 ;     OS/2 is able to access the drive using it's extended geometry.
    1530 ;     Note that DANIS506 will use 255/127 and IBM1S506 will use 255/255 geometry !
    1531 ;     Using DANI or IBM influences the location of the LVM info-sectors !
    1532 
    1533 ; 0 = This drive is below the 65536*255*63 (1052835840) boundary.
    1534 ;     OS/2 is able to access this drive using the standard 255/63 geometry.
    1535 
    1536 ; So, any return value >0 means OS/2 extended geometry will be used.
    1537 ; Value 1 will use 255/127 with DANIS506 but 255/255 with IBM1S506.
    1538 ; Values 2 and 3 will use 255/255 on both drivers.
    1539 ; You can or with 0x01 and check for 3 in this case.
    1540 ; Any value above 3 will be a drive who's capacity cannot be fully used by OS/2
    1541 ; The upper limit of 65536*255*255 will be in effect here.
    1542 
    1543 ; Note this function currently handles the boot-drive only !
    1544 ; It should be extended and use dl for the drive-number as a parameter.
    1545 ; Because we use this function to get this info in a number of places,
    1546 ; all regs and flags except AX are saved and restored.
    1547 
    1548 ; DL contains BIOS disk-number; 80h for first, 81h for second, etc.
     1455;##############################################################################
     1456;# There is much information to know about the connected disks.
     1457;# We also want this information clustered per disk and available before
     1458;# further disk and partition scanning takes place.
     1459;# This function gathers such information like INT13, INT13X, MBR, LVM, more.
     1460;# Especially important is the LVM information, because that contains the
     1461;# geometry OS/2 uses to access the disk. Other important information is the
     1462;# presence of valid MBRs, logical partitions and whatnot.
     1463;# This function gathers such information and stores it in a DISKINFO structure
     1464;# for which an instance exists for every disk found.
     1465;##############################################################################
     1466;# ACTION   : Gather disk information and store this in the BSS
     1467;# ----------------------------------------------------------------------------
     1468;# EFFECTS  : Modifies DAP structure and the buffers it uses, fills DISKINFO[n]
     1469;# ----------------------------------------------------------------------------
     1470;# IN       : DL     - BIOS disk number (80h,81h,etc)
     1471;# ----------------------------------------------------------------------------
     1472;# OUT      : CF=1   - failure
     1473;##############################################################################
    15491474DriveIO_GatherDiskInfo  Proc Near
    15501475
    15511476IFDEF   AUX_DEBUG
    1552         IF 0
     1477        IF 1
    15531478        DBG_TEXT_OUT_AUX    'DriveIO_GatherDiskInfo:'
    15541479        PUSHRF
     
    15601485ENDIF
    15611486
    1562         pushf
    1563         push    bx
    1564         push    cx
    1565         push    dx
    1566         push    si
    1567         push    di
     1487        ; Push all registers we use
     1488        pusha
     1489        push    ds
    15681490        push    es
    15691491
    1570         ; Set ES to CS for buffer clearing
    1571         push    cs
     1492        ; Make sure ES=DS
     1493        push    ds
    15721494        pop     es
    15731495
    1574         ; Clear the buffer
    1575         ; Also setup the buffer size.
    1576         ; Old Phoenix BIOSses require word (flags) at 02 to be zero,
    1577         ; so we clear the whole buffer to be sure.
    1578         mov     cx, i13xbuf_size        ; Dynamically calculated by assembler.
    1579         mov     di, offset [i13xbuf]    ; Points to size field.
    1580         mov     [di],cx                 ; Setup buffer-size.
    1581         inc     di
    1582         inc     di                      ; Now pointing at actual buffer.
    1583         xor     ah,ah                   ; Fill value.
    1584         cld                             ; Direction up.
    1585         rep stosb                       ; Clear buffer.
    1586 
    1587         ; Get the drive parameters
    1588         mov     ah, 48h                 ; Get Drive Parameters (extended version)
    1589         ;mov     dl, 80h                ; Drive number
    1590         mov     si, offset [i13xbuf]    ; Buffer for result-info
    1591         push    dx
    1592         int     13h                     ; Call the BIOS-function
    1593         pop     dx
    1594 
    1595         ; Do some error-checking
    1596         or      ah,ah                       ; AH is zero if no error (ZF=1 if no error)
    1597         mov     ax,0                        ; Setup code for non-huge drive (does not influence ZF)
    1598         jz      DriveIO_GatherDiskInfo_ok   ; Return if error (AL<>0 thus ZF=0) but CY not set, assuming non-huge drive
    1599         jnc     DriveIO_GatherDiskInfo_ok   ; Return if error (CY=1), assuming non-huge drive
     1496        ; Check if BIOS disk number is valid
     1497        call    DriveIO_IsValidHarddisk
     1498        jc      DriveIO_GatherDiskInfo_error
     1499
     1500        ; Calculate the entry in the DISKINFO array for this disk
     1501        call    DriveIO_CalcDiskInfoPointer
     1502
     1503        ; Save the entry for later recalls
     1504        mov     bp, bx
     1505
     1506        ; Store the BIOS disk number in the structure
     1507        mov     [bx+LocDISKINFO_DiskNum], dl
     1508
     1509; ------------------------------------------------------------------- [ INT13 ]
     1510
     1511        ; Get BIOS Disk Parameters (legacy method)
     1512        mov     ah, 08h                         ; Get Disk Parameters
     1513        int     13h                             ; Call BIOS
     1514
     1515        ; CF=1 or AH!=0 indicates error
     1516        jc      DriveIO_GatherDiskInfo_error
     1517        test    ah, ah
     1518        jnz     DriveIO_GatherDiskInfo_error
     1519
     1520        ; Recall DISKINFO entry
     1521        mov     bx, bp
     1522
     1523        ; Store SPT (WORD)
     1524        xor     ah, ah                          ; Zero extend SPT to 16 bits
     1525        mov     al, cl                          ; Hi 2 bits max cyl and max sec
     1526        and     al, 3fh                         ; Mask max sec (1-based)
     1527        mov     [bx+LocDISKINFO_I13_Secs], ax   ; Store SPT
     1528
     1529        ; Store HEADS (WORD)
     1530        xor     dl, dl                          ; Zero extend HEADS to 16 bits
     1531        xchg    dl, dh                          ; Get max head (0-based)
     1532        inc     dx                              ; Head count
     1533        mov     [bx+LocDISKINFO_I13_Heads], dx  ; Store HEADS
     1534
     1535        ; Store CYLS (WORD)
     1536        shr     cl, 6                           ; Hi 2 bits of max cyl to 1:0
     1537        xchg    cl, ch                          ; Max cyl (0-based)
     1538        inc     cx                              ; Cyl count
     1539        mov     [bx+LocDISKINFO_I13_Cyls], cx   ; Store CYLS
     1540
     1541        ; Recall BIOS disk number
     1542        mov     dl, [bx+LocDISKINFO_DiskNum]
     1543
     1544; ------------------------------------------------------------------ [ INT13X ]
     1545
     1546        ; Get BIOS Disk Parameters (extended method)
     1547        mov     si, offset [Scratch]            ; Buffer to return disk info
     1548        mov     ax, 80h                         ; Size of buffer
     1549        mov     [si], ax                        ; Store it in first word
     1550        mov     ah, 48h                         ; Get Extended Disk Parameters
     1551        int     13h                             ; Call BIOS
     1552
     1553        ; CF=1 or AH!=0 indicates error
     1554        jc      DriveIO_GatherDiskInfo_error
     1555        test    ah, ah
     1556        jnz     DriveIO_GatherDiskInfo_error
     1557
     1558        ; Store flags (WORD)
     1559        cld                                         ; Direction up
     1560        lodsw                                       ; Buffersize, discard
     1561        lodsw                                       ; Flags (CHS valid etc)
     1562        mov     [bx+LocDISKINFO_I13X_Flags], ax     ; Store them
     1563
     1564        ; Store CYLS (DWORD)
     1565        lodsw                                       ; Cyl count low
     1566        mov     [bx+LocDISKINFO_I13X_Cyls+00h], ax  ; Store CYLS low
     1567        lodsw                                       ; Cyl count high
     1568        mov     [bx+LocDISKINFO_I13X_Cyls+02h], ax  ; Store CYLS high
     1569
     1570        ; Store HEADS (DWORD)
     1571        lodsw                                       ; Head count low
     1572        mov     [bx+LocDISKINFO_I13X_Heads+00h], ax ; Store HEADS low
     1573        lodsw                                       ; Head count high
     1574        mov     [bx+LocDISKINFO_I13X_Heads+02h], ax ; Store HEADS high
     1575
     1576        ; Store SPT (DWORD)
     1577        lodsw                                       ; Secs per track low
     1578        mov     [bx+LocDISKINFO_I13X_Secs+00h], ax  ; Store SPT low
     1579        lodsw                                       ; Secs per track high
     1580        mov     [bx+LocDISKINFO_I13X_Secs+02h], ax  ; Store SPT high
     1581
     1582        ; Store total LBA sectors (QWORD)
     1583        lea     di, [bx+LocDISKINFO_I13X_SecsLBA]
     1584        mov     cx, 4
     1585        rep     movsw
     1586
     1587        ; Store sector size (WORD)
     1588        lodsw
     1589        mov     [bx+LocDISKINFO_I13X_SecSize], ax
     1590
     1591        ; Store bus name (4 bytes, space padded, v3.0+)
     1592        lea     si, [Scratch+24h]
     1593        lea     di, [bx+LocDISKINFO_I13X_HostBus]
     1594        movsw
     1595        movsw
     1596
     1597        ; Store interface name (8 bytes, space padded, v3.0+)
     1598        lea     di, [bx+LocDISKINFO_I13X_Interface]
     1599        mov     cx, 4
     1600        rep     movsw
     1601
     1602        ; Should gather some more INT13X info here,
     1603        ; like maybe Advanced Format stuff or so.
     1604        ; We'll investigate that at a later time.
     1605
     1606; --------------------------------------------------------------------- [ MBR ]
     1607
     1608        ; Load the MBR
     1609        mov     si, offset [TmpSector]
     1610        call    DriveIO_LoadMBR
     1611
     1612        ; Store MBR flags (valid sig, partitions present, airboot installed)
     1613        mov     [bx+LocDISKINFO_MbrFlags], al
     1614
     1615        ; Recall BIOS disk number
     1616        mov     dl, [bx+LocDISKINFO_DiskNum]
     1617
     1618; --------------------------------------------------------------------- [ LVM ]
     1619
     1620        ; Locate the Master LVM sector, if any
     1621        call    DriveIO_LocateMasterLVMSector
     1622
     1623        ; Save Master LVM sector LBA high
     1624        mov     cx, bx
     1625
     1626        ; Recall DISKINFO entry
     1627        mov     bx, bp
     1628
     1629        ; Store Master LVM sector LBA
     1630        mov     [bx+LocDISKINFO_LVM_MasterLBA+00h], ax
     1631        mov     [bx+LocDISKINFO_LVM_MasterLBA+02h], cx
     1632
     1633        ; No Master LVM sector found, so skip storing LVM info for this disk
     1634        jnc     DriveIO_GatherDiskInfo_no_master_lvm
     1635
     1636        ; Load the Master LVM sector into [LVMSector]
     1637        call    DriveIO_LoadMasterLVMSector
     1638
     1639        ; No valid Master LVM sector, so skip storing LVM info for this disk
     1640        jc      DriveIO_GatherDiskInfo_no_master_lvm
     1641
     1642        ; A valid Master LVM sector has been loaded into [LVMSector]
     1643        mov     si, offset [LVMSector]
     1644
     1645        ; Get the number of sectors per track (OS/2 geometry)
     1646        mov     ax, [si+LocLVM_Secs+00h]
     1647        mov     cx, [si+LocLVM_Secs+02h]
     1648
     1649        ; Store it
     1650        mov     [bx+LocDISKINFO_LVM_Secs+00h], ax
     1651        mov     [bx+LocDISKINFO_LVM_Secs+02h], cx
     1652
     1653        ; Get the number of heads (OS/2 geometry)
     1654        mov     ax, [si+LocLVM_Heads+00h]
     1655        mov     cx, [si+LocLVM_Heads+02h]
     1656
     1657        ; Store it
     1658        mov     [bx+LocDISKINFO_LVM_Heads+00h], ax
     1659        mov     [bx+LocDISKINFO_LVM_Heads+02h], cx
     1660
     1661        ; Should gather some more LVM info here,
     1662        ; like OS/2 extended geometry and other flags.
     1663        ; We'll implement that at a later time.
     1664
     1665    DriveIO_GatherDiskInfo_no_master_lvm:
     1666
     1667        ; When no Master LVM sector was found,
     1668        ; the LVM info in the DISKINFO structure for the disk
     1669        ; will be ZERO because the area was cleared in PRECRAP.
     1670
     1671        ; Indicate success
     1672        clc
     1673
    16001674        jmp     DriveIO_GatherDiskInfo_ret
    16011675
    1602 
    1603     DriveIO_GatherDiskInfo_ok:
    1604 
    1605         ;
    1606         ; Store the drive geometry
    1607         ;
    1608 
    1609         mov      si, offset i13xbuf
    1610 
    1611         xor      dh,dh
    1612         and      dl,01111111b
    1613         shl      dx,1
    1614         shl      dx,1
    1615 
    1616         ; Store number of cylinders on disk
    1617         mov      bx, offset BIOS_Cyls
    1618         add      bx,dx
    1619         mov      ax,[si+04h]
    1620 
    1621         mov      word ptr [bx+00],ax
    1622         mov      ax,[si+06]
    1623         mov      word ptr [bx+02],ax
    1624 
    1625         ; Store number of heads per cylinder
    1626         mov      bx, offset BIOS_Heads
    1627         add      bx,dx
    1628         mov      ax,[si+08h]
    1629         mov      word ptr [bx+00],ax
    1630         mov      ax,[si+0ah]
    1631         mov      word ptr [bx+02],ax
    1632 
    1633         ; Store number of sectors per track
    1634         mov      bx, offset BIOS_Secs
    1635         add      bx,dx
    1636         mov      ax,[si+0ch]
    1637         mov      word ptr [bx+00],ax
    1638 
    1639         ; Update first byte of translation-table to conform to BIOS SPT
    1640         ; rousseau.comment.201610122010
    1641         ; Very bad !!
    1642         ; This table is global and the instruction below would change the
    1643         ; first (last checked) 'well known' SPT value to the SPT value of
    1644         ; the last disk scanned. This goes wrong when the last disk scanned
    1645         ; has a SPT <63, which is often the case when an USB stick is present
    1646         ; when AirBoot starts.
    1647         ;~ mov      byte ptr [secs_per_track_table], al
    1648 
    1649         mov      ax,[si+0eh]
    1650         mov      word ptr [bx+02],ax
    1651 
    1652         ; Store total secs
    1653         mov      bx, offset [BIOS_TotalSecs]
    1654         add      bx,dx
    1655         add      bx,dx
    1656         mov      ax,[si+10h]
    1657 
    1658         mov      word ptr [bx+00],ax
    1659         mov      ax,[si+12h]
    1660         mov      word ptr [bx+02],ax
    1661         mov      ax,[si+14h]
    1662         mov      word ptr [bx+04],ax
    1663         mov      ax,[si+18h]
    1664         mov      word ptr [bx+06],ax
    1665 
    1666         ; Store number of bytes per sector
    1667         mov      bx, offset [BIOS_Bytes]
    1668         add      bx,dx
    1669         mov      ax,[si+18h]
    1670         mov      [bx],ax
    1671 
    1672 
    1673         ;
    1674         ; See of it's a huge drive of not
    1675         ;
    1676 
    1677         ; Drive is larger than 2TiB
    1678         mov     ax,5                        ; Drive code (5)
    1679         mov     bx, [si+14h]                ; Low word of high dword of sector-count
    1680         or      bx, [si+16h]                ; High word of high dword of sector-count
    1681         jnz     DriveIO_GatherDiskInfo_ret  ; If non-zero we have a drive with >2^32 sectors and thus LBA48 addressing
    1682 
    1683         ; Drive is larger than max OS/2 capacity
    1684         dec     ax                          ; Drive code (4)
    1685         mov     bx, [si+12h]                ; High word of low dword of sector-count
    1686         cmp     bx, 0fe01h                  ; Boundary
    1687         jae     DriveIO_GatherDiskInfo_ret  ; If above or equal to boundary,
    1688                                             ; we have a drive larger than to 65536*255*255 = FE010000 sectors
    1689 
    1690         ; Drive can be completely utilized by OS/2
    1691         dec     ax                          ; Drive code (3)
    1692         cmp     bx, 8000h                   ; Boundary
    1693         jae     DriveIO_GatherDiskInfo_ret  ; If above or equal to boundary,
    1694                                             ; we have a drive larger than 2^31 sectors but smaller than 65536*255*255
    1695 
    1696         ; This is the small area between DANI 1TiB and LBA 1TiB
    1697         dec     ax                          ; Drive code (2)
    1698         cmp     bx, 7e81h                   ; Boundary
    1699         jae     DriveIO_GatherDiskInfo_ret  ; If above or equal to boundary,
    1700                                             ; we have a drive larger than 65536*255*127 but <65536*255*255
    1701                                             ; DANIS506.ADD will use 255/255 extended geometry
    1702 
    1703         ; DANI will use 255/127 in this area, this could impact the location of LVM-sectors ! (last sec on track)
    1704         dec     ax                          ; Drive code (1)
    1705         cmp     bx, 3ec1h                   ; Boundary
    1706         jae     DriveIO_GatherDiskInfo_ret  ; If above or equal to boundary,
    1707                                             ; we have a drive larger than 65536*255*63 sectors (OS/2 502GiB Limit!)
    1708                                             ; DANIS506.ADD will use 255/127 extended geometry !
    1709                                             ; IBM1S506.ADD will use 255/255 extended geometry !
    1710 
    1711         ; We have a drive that can be addressed using standard 255/63 geometry
    1712         dec     ax                                      ; Drive code (0)
    1713                                             ; We have a drive smaller than 65536*255*63 = 3EC10000 sectors
    1714 
     1676    DriveIO_GatherDiskInfo_error:
     1677        stc
    17151678    DriveIO_GatherDiskInfo_ret:
     1679
     1680
     1681IFDEF   AUX_DEBUG
     1682        IF 1
     1683        DBG_TEXT_OUT_AUX    '[DISKINFO]'
     1684        PUSHRF
     1685            call    DEBUG_DumpRegisters
     1686            ;~ call    AuxIO_DumpParagraph
     1687            ;~ call    AuxIO_TeletypeNL
     1688            mov     si, bp
     1689            mov     cx, 4
     1690        @@:
     1691            call    AuxIO_DumpParagraph
     1692            call    AuxIO_TeletypeNL
     1693            add     si, 16
     1694            loop @B
     1695            mov     si, offset [Scratch]
     1696            mov     cx, 4
     1697        @@:
     1698            call    AuxIO_DumpParagraph
     1699            call    AuxIO_TeletypeNL
     1700            add     si, 16
     1701            loop @B
     1702            mov     si, offset [LVMSector]
     1703            mov     cx, 7
     1704        @@:
     1705            call    AuxIO_DumpParagraph
     1706            call    AuxIO_TeletypeNL
     1707            add     si, 16
     1708            loop @B
     1709        POPRF
     1710        ENDIF
     1711ENDIF
     1712
     1713        ; Restore registers
    17161714        pop     es
    1717         pop     di
    1718         pop     si
    1719         pop     dx
    1720         pop     cx
    1721         pop     bx
    1722 
    1723         mov      byte ptr [CurIO_UseExtension],1
    1724 
    1725         popf
     1715        pop     ds
     1716        popa
     1717
    17261718        ret
    17271719DriveIO_GatherDiskInfo  EndP
     
    17641756
    17651757; Values for sectors per track table corresponding to DriveIO_IsHugeDrive return value.
    1766 secs_per_track_table    db    63,127,255,255,255,255
     1758;~ secs_per_track_table    db    63,127,255,255,255,255
    17671759
    17681760;~ db_lmlvm    db 'Load Master LVM -- disk: ',0
Note: See TracChangeset for help on using the changeset viewer.