Author: wmb Date: Sat Aug 6 00:23:50 2011 New Revision: 2416 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2416
Log: Added GIUD Partition Table support.
Added: ofw/disklabel/gpt.fth ofw/disklabel/gpttools.fth ofw/disklabel/showgpt.fth Modified: cpu/arm/basefw.bth cpu/x86/basefw.bth ofw/disklabel/loadpkg.fth ofw/disklabel/methods.fth ofw/fs/fatfs/fdisk2.fth ofw/fs/fatfs/partition.fth
Modified: cpu/arm/basefw.bth ============================================================================== --- cpu/arm/basefw.bth Fri Aug 5 03:16:10 2011 (r2415) +++ cpu/arm/basefw.bth Sat Aug 6 00:23:50 2011 (r2416) @@ -66,12 +66,12 @@ fload ${BP}/ofw/fs/cdfs/loadpkg.fth \ ISO 9660 CD-ROM file system reader end-support-package
+fload ${BP}/ofw/disklabel/gpttools.fth + support-package: disk-label fload ${BP}/ofw/disklabel/loadpkg.fth \ Disk label package end-support-package -[then]
-[ifdef] resident-packages fload ${BP}/ofw/fs/fatfs/fdisk2.fth \ Partition map administration [else] autoload: fdisk2.fth
Modified: cpu/x86/basefw.bth ============================================================================== --- cpu/x86/basefw.bth Fri Aug 5 03:16:10 2011 (r2415) +++ cpu/x86/basefw.bth Sat Aug 6 00:23:50 2011 (r2416) @@ -105,6 +105,8 @@ end-support-package [then]
+fload ${BP}/ofw/disklabel/gpttools.fth + support-package: disk-label fload ${BP}/ofw/disklabel/loadpkg.fth \ Disk label package end-support-package
Added: ofw/disklabel/gpt.fth ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ ofw/disklabel/gpt.fth Sat Aug 6 00:23:50 2011 (r2416) @@ -0,0 +1,74 @@ +: gpt? ( -- flag ) + sector-buf h# 1fe + le-w@ h# aa55 <> if false exit then + sector-buf h# 1c2 + c@ gpt-type = +; + +\ Tasks: +\ Choose a partition based on part# and partition-name$ +\ Set sector-offset, size-low, size-high, and partition-type + +-1 value the-sector +: get-gpt-info ( -- error? ) + 1 read-hw-sector ( ) + sector-buf gpt-magic comp if true exit then + \ XXX should verify CRC + sector-buf d# 72 + le-x@ to partition-lba0 + sector-buf d# 80 + le-l@ to #gpt-partitions + sector-buf d# 84 + le-l@ to /gpt-entry + -1 to the-sector + false +; +: read-gpt-sector ( sector# -- ) + dup the-sector = if drop exit then ( sector# ) + dup to the-sector ( sector# ) + read-hw-sector +; + +: select-gpt-partition ( adr -- ) + dup gpt-blk0 x>u to sector-offset ( adr ) + gpt-#blks /sector xu*d to size-high to size-low ( ) +; + +: partition-name= ( adr -- flag ) + d# 56 + ( utf16-name-adr ) + partition-name$ bounds ?do ( utf16-name-adr ) + dup w@ i c@ <> if ( utf16-name-adr ) + drop false unloop exit ( -- false ) + then ( utf16-name-adr ) + wa1+ ( utf16-name-adr' ) + loop ( utf16-name-adr ) + w@ 0= ( flag ) +; + +: >gpt-entry ( n -- adr ) + /gpt-entry * ( offset ) + /sector /mod ( rem quot ) + partition-lba0 x>u + ( rem sector# ) + read-gpt-sector ( rem ) + sector-buf + ( adr ) +; +: nth-gpt-partition ( n -- ) + 1- >gpt-entry select-gpt-partition ( ) +; +: gpt-active? ( adr -- flag ) d# 16 0 bskip 0<> ; + +: named-gpt-partition ( -- ) + #gpt-partitions 0 ?do + i >gpt-entry ( adr ) + dup gpt-active? if ( adr ) + dup partition-name= if ( adr ) + select-gpt-partition ( ) + leave ( ) + then ( adr ) + then ( adr ) + drop ( ) + loop ( ) +; +: gpt-map ( -- ) + get-gpt-info abort" Invalid GUID Partition Table" + #part 1 >= if + #part nth-gpt-partition + else + named-gpt-partition + then +;
Added: ofw/disklabel/gpttools.fth ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ ofw/disklabel/gpttools.fth Sat Aug 6 00:23:50 2011 (r2416) @@ -0,0 +1,20 @@ +32\ : le-x@ ( adr -- x ) dup le-l@ swap la1+ le-l@ ; +0 value #gpt-partitions +0 value /gpt-entry +32\ 0. 2value partition-lba0 +32\ alias x>u drop +32\ alias u>x u>d +32\ alias x+ d+ +32\ alias x- d- +32\ alias xswap 2swap +32\ : onex 1. ; +: du* ( d1 u -- d2 ) + tuck u* >r ( d1.lo u r: d2.hi ) + um* 0 r> d+ ( d2 ) +; +32\ : xu*d ( x u -- d ) du* ; +64\ alias xu*d um* + +: gpt-magic ( -- adr len ) " EFI PART" ; +: gpt-blk0 ( adr -- d.blk0 ) d# 32 + le-x@ ; +: gpt-#blks ( adr -- d.blks ) dup d# 40 + le-x@ rot gpt-blk0 x- onex d+ ;
Modified: ofw/disklabel/loadpkg.fth ============================================================================== --- ofw/disklabel/loadpkg.fth Fri Aug 5 03:16:10 2011 (r2415) +++ ofw/disklabel/loadpkg.fth Sat Aug 6 00:23:50 2011 (r2416) @@ -12,6 +12,7 @@ [ifdef] hfs-support fload ${BP}/ofw/fs/macfs/partition.fth [then] +fload ${BP}/ofw/disklabel/gpt.fth fload ${BP}/ofw/disklabel/methods.fth
\ LICENSE_BEGIN
Modified: ofw/disklabel/methods.fth ============================================================================== --- ofw/disklabel/methods.fth Fri Aug 5 03:16:10 2011 (r2415) +++ ofw/disklabel/methods.fth Sat Aug 6 00:23:50 2011 (r2416) @@ -80,6 +80,8 @@ mac-disk? if mac-map exit then [then]
+ gpt? if gpt-map exit then + fdisk? if fdisk-map exit then
\ We check for ISO 9660 after the ones above, because they can be @@ -162,6 +164,7 @@ \ <digit>: FDISK partition number \ <letter>: UFS partition letter (a..h) \ <digit><letter>: UFS partition embedded within FDISK partition +\ -<decimal-digits>: The last N blocks of the disk
\ partition# is one of: \ -1, meaning the default partition, i.e. no partition was specified @@ -171,15 +174,26 @@ \ In addition, ufs-partition is set to the UFS partition letter (a..h) \ if the string appears to contain a letter.
-: parse-partition ( -- ) - null$ to filename -1 to #part 0 to ufs-partition +: decode-partition ( adr len -- rem$ ) + \ If the string parses as a decimal number, it's a partition# if + \ positive or the last N blocks if negative + 2dup push-decimal $number pop-base 0= if ( adr len n ) + dup 0< if ( adr len n ) + /sector um* ( adr len d.partition-size ) + get-disk-size size-low size-high ( adr len d.partition-size d.disk-size ) + 2over d- /sector um/mod nip ( adr len d.partition-size partition-sector ) + to sector-offset ( adr len d.partition-size ) + to size-high to size-low ( adr len ) + -2 to #part ( adr len ) \ Tell select-partition + else ( adr len n ) + to #part ( adr len ) + then ( adr len ) + drop 0 ( adr 0 ) + exit ( rem$ -- ) + then ( adr len )
- my-args ( adr len ) - - \ An empty arg string is treated as a null partition and a null filename - dup 0= if 2drop exit then ( adr len ) - - \ If the first character of the string is a digit, it's a partition # + \ If the first character of the string is a decimal number, it's a partition #, + \ possibly followed by UFS partition letter over c@ ascii 0 ascii 9 between if ( adr len ) over c@ ascii 0 - to #part ( adr len ) 1 /string ( adr' len' ) @@ -192,28 +206,24 @@ 1 /string ( adr' len' ) dup 0= if 2drop exit then ( adr len ) then ( adr len ) +; +: parse-partition ( -- ) + null$ to filename null$ to partition-name$ -1 to #part 0 to ufs-partition
- \ If the first character is "-", it is followed by a decimal number N and - \ the "partition" is the last N blocks - over c@ ascii - = if ( adr len ) - 1 /string ( adr' len' ) - push-decimal $number pop-base if ( ) - ." Bad decimal number after '-' in partition spec" cr - exit - then ( n ) - /sector um* ( d.partition-size ) - get-disk-size size-low size-high ( d.partition-size d.disk-size ) - 2over d- /sector um/mod nip ( d.partition-size partition-sector ) - to sector-offset ( d.partition-size ) - to size-high to size-low ( ) - -2 to #part ( ) \ Tell select-partition - exit - then ( adr len ) + my-args ( adr len )
- \ If the first character of the string is ",", discard it - over c@ ascii , = if ( adr len ) - 1 /string ( adr' len' ) - then ( adr' len' ) + \ An empty arg string is treated as a null partition and a null filename + dup 0= if 2drop exit then ( adr len ) + + \ If the string contains a comma, the first half is the partition name + " ," lex if ( tail$ head$ delim ) + drop 2dup to partition-name$ ( tail$ head$ ) + decode-partition 2drop ( tail$ ) + to filename ( ) + exit ( -- ) + then ( adr len ) + + decode-partition ( rem$ )
\ The remainder of the string, if any, is the filename to filename @@ -239,7 +249,7 @@ : close ( -- ) sector-buf if sector-buf /sector free-mem then ; : size ( -- d ) size-low size-high ; : load ( adr -- len ) - \ This load method is used only for type 41 partitions + \ This load method is used only for type 41 (IBM "PREP") partitions partition-type h# 41 <> if drop 0 exit then
0 0 " seek" $call-parent drop ( adr )
Added: ofw/disklabel/showgpt.fth ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ ofw/disklabel/showgpt.fth Sat Aug 6 00:23:50 2011 (r2416) @@ -0,0 +1,180 @@ +\ See license at end of file +purpose: GUID Partition Table handler + +d# 512 value /gpt-sector + +32\ : read-gpt-sector ( x.lba# -- ) +32\ drop /gpt-sector um* " seek" disk-dev $call-method drop +32\ sector-buf /gpt-sector " read" disk-dev $call-method drop +32\ ; +0 value gpt-entries/sector + +-1 value this-sector +: get-gpt-entry ( partition# -- adr ) + gpt-entries/sector /mod ( rem quot ) + dup this-sector <> if ( rem quot ) + dup to this-sector ( rem quot ) + u>x partition-lba0 x+ ( rem lba# ) + read-gpt-sector ( rem ) + else ( rem quot ) + drop ( rem ) + then ( rem ) + /gpt-entry * sector-buf + ( adr ) +; +: .gpt-bounds ( adr -- ) + push-hex + dup gpt-blk0 d# 12 ud.r space ( adr ) + gpt-#blks d# 10 ud.r space ( ) + pop-base ( ) +; +: utf16-emit ( w -- ) + wbsplit if + \ Emit "?" for code points we can't handle + drop ." ?" + else + \ Don't emit nulls + ?dup if emit then + then +; +: .gpt-name ( adr -- ) + d# 56 + d# 72 bounds do + i w@ utf16-emit + /w +loop +; +string-array partition-type-guids +," 00000000-0000-0000-0000-000000000000" ," Unused entry" +," 024DEE41-33E7-11D3-9D69-0008C781F39F" ," MBR scheme" +," C12A7328-F81F-11D2-BA4B-00A0C93EC93B" ," EFI System" +," 21686148-6449-6E6F-744E-656564454649" ," BIOS Boot" +," E3C9E316-0B5C-4DB8-817D-F92DF00215AE" ," Windows Reserved" +," EBD0A0A2-B9E5-4433-87C0-68B6B72699C7" ," Windows Basic data" +," 5808C8AA-7E8F-42E0-85D2-E1E90434CFB3" ," Windows LDM metadata" +," AF9B60A0-1431-4F62-BC68-3311714A69AD" ," Windows LDM data" +," DE94BBA4-06D1-4D40-A16A-BFD50179D6AC" ," Windows Recovery Environment" +," 37AFFC90-EF7D-4E96-91C3-2D7AE055B174" ," Windows IBM GPFS" +," 75894C1E-3AEB-11D3-B7C1-7B03A0000000" ," HP-UX Data" +," E2A1E728-32E3-11D6-A682-7B03A0000000" ," HP-UX Service" +," 0FC63DAF-8483-4772-8E79-3D69D8477DE4" ," Linux filesystem data" +," A19D880F-05FC-4D3B-A006-743F0F84911E" ," Linux RAID" +," 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F" ," Linux Swap" +," E6D6D379-F507-44C2-A23C-238F2A3DF928" ," Linux LVM" +," 8DA63339-0007-60C0-C436-083AC8230908" ," Linux Reserved" +," 83BD6B9D-7F41-11DC-BE0B-001560B84F0F" ," FreeBSD Boot" +," 516E7CB4-6ECF-11D6-8FF8-00022D09712B" ," FreeBSD Data" +," 516E7CB5-6ECF-11D6-8FF8-00022D09712B" ," FreeBSD Swap" +," 516E7CB6-6ECF-11D6-8FF8-00022D09712B" ," FreeBSD UFS" +," 516E7CB8-6ECF-11D6-8FF8-00022D09712B" ," FreeBSD Vinum volume manager" +," 516E7CBA-6ECF-11D6-8FF8-00022D09712B" ," FreeBSD ZFS" +," 48465300-0000-11AA-AA11-00306543ECAC" ," Apple HFS+" +," 55465300-0000-11AA-AA11-00306543ECAC" ," Apple UFS" +," 6A898CC3-1DD2-11B2-99A6-080020736631" ," Apple ZFS" +," 52414944-0000-11AA-AA11-00306543ECAC" ," Apple RAID" +," 52414944-5F4F-11AA-AA11-00306543ECAC" ," Apple RAID offline" +," 426F6F74-0000-11AA-AA11-00306543ECAC" ," Apple Boot" +," 4C616265-6C00-11AA-AA11-00306543ECAC" ," Apple Label" +," 5265636F-7665-11AA-AA11-00306543ECAC" ," Apple TV Recovery" +," 6A82CB45-1DD2-11B2-99A6-080020736631" ," Solaris Boot" +," 6A85CF4D-1DD2-11B2-99A6-080020736631" ," Solaris Root" +," 6A87C46F-1DD2-11B2-99A6-080020736631" ," Solaris Swap" +," 6A8B642B-1DD2-11B2-99A6-080020736631" ," Solaris Backup" +," 6A898CC3-1DD2-11B2-99A6-080020736631" ," Solaris /usr" +," 6A8EF2E9-1DD2-11B2-99A6-080020736631" ," Solaris /var" +," 6A90BA39-1DD2-11B2-99A6-080020736631" ," Solaris /home" +," 6A9283A5-1DD2-11B2-99A6-080020736631" ," Solaris Alternate sector" +," 6A945A3B-1DD2-11B2-99A6-080020736631" ," Solaris Reserved" +," 6A9630D1-1DD2-11B2-99A6-080020736631" ," Solaris Reserved" +," 6A980767-1DD2-11B2-99A6-080020736631" ," Solaris Reserved" +," 6A96237F-1DD2-11B2-99A6-080020736631" ," Solaris Reserved" +," 6A8D2AC7-1DD2-11B2-99A6-080020736631" ," Solaris Reserved" +," 49F48D32-B10E-11DC-B99B-0019D1879648" ," NetBSD Swap" +," 49F48D5A-B10E-11DC-B99B-0019D1879648" ," NetBSD FFS" +," 49F48D82-B10E-11DC-B99B-0019D1879648" ," NetBSD LFS" +," 49F48DAA-B10E-11DC-B99B-0019D1879648" ," NetBSD RAID" +," 2DB519C4-B10F-11DC-B99B-0019D1879648" ," NetBSD Concatenated" +," 2DB519EC-B10F-11DC-B99B-0019D1879648" ," NetBSD Encrypted" +," FE3A2A5D-4F32-41A7-B725-ACCC3285A309" ," ChromeOS kernel" +," 3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC" ," ChromeOS rootfs" +," 2E0A753D-9E48-43B0-8337-B15192CB1B5E" ," ChromeOS future-use" +end-string-array + +\ Convert the binary encoding of a GUID to the text encoding +\ The first three components are in native byte order - which I think +\ means little-endian for GPT GUIDs. The last two components are big-endian. +d# 36 buffer: 'guid + +: >guid$ ( adr -- adr len ) + push-hex ( adr ) + dup le-l@ (.8) 'guid swap move + + [char] - 'guid 8 + c! + dup 4 + le-w@ (.4) 'guid d# 9 + swap move + + [char] - 'guid d# 13 + c! + dup 6 + le-w@ (.4) 'guid d# 14 + swap move + + [char] - 'guid d# 18 + c! + dup 8 + be-w@ (.4) 'guid d# 19 + swap move + + [char] - 'guid d# 23 + c! + d# 10 + ( adr ) + 6 0 do ( adr ) + dup i + c@ (.2) ( adr $ ) + 'guid d# 24 + i wa+ swap move ( adr ) + loop ( adr ) + drop ( ) + + pop-base ( ) + + 'guid d# 36 2dup upper ( adr len ) +; + +: .gpt-type ( adr -- ) + >guid$ 2>r 0 ( string# r: guid$ ) + begin ( string# r: guid$ ) + dup ['] partition-type-guids ( string# string# xt r: guid$ ) + catch 0= while ( string# 'this r: guid$ ) + count 2r@ $= if ( string# r: guid$ ) + 1+ partition-type-guids count type ( r: guid$ ) + 2r> 2drop exit ( -- ) + then ( string# r: guid$ ) + 2+ ( string#' r: guid$ ) + repeat ( string# x r: guid$ ) + 2r> type ( string# x ) + 2drop ( ) +; + +: .gpt-partition ( adr # -- ) + \ Skip unused entries + over 8 0 bskip 0= if 2drop exit then ( adr i ) + push-decimal 2 u.r space pop-base ( adr ) + dup .gpt-bounds ( adr ) + dup .gpt-name ( adr ) +\ dup .gpt-guid ( adr ) + d# 50 to-column ( adr ) + dup .gpt-type ( adr ) + drop cr ( ) +; +: .gpt-partitions ( -- ) + cr + ." # FirstBlk NumBlks Name Type" cr + ." - -------- ------- ---- ----" cr + #gpt-partitions 0 do ( ) + i get-gpt-entry i 1+ .gpt-partition ( ) + loop ( ) +; +: .gpt ( -- ) + onex read-gpt-sector + sector-buf gpt-magic comp if + ." Bad signature in GUID partition table header" cr + exit + then + push-hex +\ ." FirstBlk: " sector-buf d# 40 le-x@ d. +\ ." LastBlk: " sector-buf d# 48 le-x@ d. + pop-base + sector-buf d# 72 + le-x@ to partition-lba0 + sector-buf d# 80 + le-l@ to #gpt-partitions + sector-buf d# 84 + le-l@ to /gpt-entry + /gpt-sector /gpt-entry / to gpt-entries/sector + .gpt-partitions +;
Modified: ofw/fs/fatfs/fdisk2.fth ============================================================================== --- ofw/fs/fatfs/fdisk2.fth Fri Aug 5 03:16:10 2011 (r2415) +++ ofw/fs/fatfs/fdisk2.fth Sat Aug 6 00:23:50 2011 (r2416) @@ -27,6 +27,11 @@
headerless
+0 value sector-buf +h# 200 constant /sector +0 value disk-dev +fload ${BP}/ofw/disklabel/showgpt.fth \ GUID Partition table decoding + 0 value partition# 0 value partition-offset true value primary? @@ -40,6 +45,7 @@ cr cr ; + : .0x ( n -- ) push-hex dup 9 <= if 6 u.r else ." 0x" (.2) type then \ Type field @@ -49,8 +55,7 @@ : (.1partition) ( adr -- ) dup d# 12 + le-l@ 0= if drop exit then \ Empty entry primary? 0= if dup 4 + c@ 5 = if drop exit then then \ Logical extension entry - base @ >r - decimal + push-decimal partition# dup 5 u.r 6 spaces 1+ to partition# primary? if ." Primary" else ." Logical" then \ Primary/Logical partition dup c@ if ." Yes " else ." No " then \ Boot indicator @@ -64,6 +69,7 @@ h# c of ." FAT-32 LBA" endof h# e of ." FAT-16 LBA" endof h# 83 of ." ext2 " endof \ Linux EXT2 + h# ee of ." GUID " endof dup .0x endcase \ dup 1 + .hsc @@ -72,28 +78,31 @@ \ dup 8 + le-l@ 9 u.r \ Start block 2 spaces d# 12 + le-l@ d# 1024 + d# 2048 / 6 u.r \ Size in MB - r> base ! cr + pop-base ;
-0 value sector-buf -h# 200 constant /sector -0 value disk-dev : (.partitions) ( block-adr -- ) - dup h# 1be + - 4 0 do - dup (.1partition) - dup 4 + c@ 5 = if - d# 8 + le-l@ partition-offset + - primary? if dup to partition-offset then - /sector um* " seek" disk-dev $call-method drop - dup /sector " read" disk-dev $call-method drop - false to primary? - recurse unloop exit - then - h# 10 + - loop - 2drop + dup h# 1be + ( adr partadr ) + 4 0 do ( adr partadr ) + dup (.1partition) ( adr partadr ) + dup 4 + c@ case ( adr partadr ) + 5 of ( adr partadr ) + d# 8 + le-l@ partition-offset + ( adr part-offset ) + primary? if dup to partition-offset then ( adr part-offset ) + /sector um* " seek" disk-dev $call-method drop ( adr ) + dup /sector " read" disk-dev $call-method drop ( adr ) + false to primary? ( adr ) + recurse unloop exit ( -- ) + endof ( adr partadr ) + h# ee of ( adr partadr ) + .gpt ( adr partadr ) + leave ( adr partadr ) + endof ( adr partadr ) + endcase ( adr partadr ) + h# 10 + ( adr partadr' ) + loop ( adr partadr ) + 2drop ( ) ;
: free-buf ( -- ) sector-buf /sector free-mem ;
Modified: ofw/fs/fatfs/partition.fth ============================================================================== --- ofw/fs/fatfs/partition.fth Fri Aug 5 03:16:10 2011 (r2415) +++ ofw/fs/fatfs/partition.fth Sat Aug 6 00:23:50 2011 (r2416) @@ -53,12 +53,12 @@ false ;
-\ ??? i b s n apparently means #sectors start-sector boot-indicator system-indicator -\ system-indicator: 0 no FAT, 1 12-bit FAT, 4 16-bit FAT, 5 extended, 6 over 32M -\ ... b FAT 32, c FAT 32 LBA, e FAT-16 LBA, f extended LBA +\ ??? n,s,b,t means #sectors start-sector boot-indicator type +\ type: 0 empty, 1 12-bit FAT, 4 16-bit FAT, 5 extended, 6 over 32M +\ ... b FAT 32, c FAT 32 LBA, e FAT-16 LBA, f extended LBA \ boot-indicator: 80 bootable
-: process-ptable ( -- true | i1 b1 s1 n1 i2 b2 s2 n2 i3 b3 s3 n3 i4 b4 s4 n4 false ) +: process-ptable ( -- true | n,s,b,t4 n,s,b,t3 n,s,b,t2 n,s,b,t1 false ) sector-buf h# 1fe + le-w@ h# aa55 <> if true exit then
\ Process a real partition table @@ -73,31 +73,31 @@
0 instance value extended-offset false value found? -defer suitable? ( s n -- s n flag ) +defer suitable? ( b t -- b t flag )
: (find-partition ( sector-offset -- not-found? ) - >r process-ptable if r> drop false exit then r> + >r process-ptable if r> drop false exit then r> ( n,s,b,t*4 sector-offset )
- 4 0 do ( i,b,s,nN ... i,b,s,n1 sector-offset ) - >r ( ... i,b,s,n ) - found? if \ partition was found ( ... i,b,s,n ) + 4 0 do ( n,s,b,tN ... n,s,b,t1 sector-offset ) + >r ( ... n,s,b,t ) + found? if \ partition was found ( ... n,s,b,t ) 2drop 2drop ( ... ) - else ( ... i,b,s,n ) - ?dup 0= if ( ... i,b,s ) - \ no FAT, skip it. + else ( ... n,s,b,t ) + ?dup 0= if ( ... n,s,b ) + \ empty, skip it. 3drop ( ... ) - else ( ... i,b,s,n ) - dup 5 = over h# f = or if \ extended partition ( ... i,b,s,n ) - 2drop nip ( ... b ) + else ( ... n,s,b,t ) + dup 5 = over h# f = or if \ extended partition ( ... n,s,b,t ) + 2drop nip ( ... s ) extended-offset dup 0= if over to extended-offset then + dup read-sector recurse drop ( ... ) - else \ Ordinary partition ( ... i,b,s,n ) - suitable? if ( ... i,b,s,n ) - to partition-type drop ( ... i,b ) - r@ + to sector-offset ( ... i ) + else \ Ordinary partition ( ... n,s,b,t ) + suitable? if ( ... n,s,b,t ) + to partition-type drop ( ... n,s ) + r@ + to sector-offset ( ... n ) /sector um* to size-high to size-low ( ... ) true to found? ( ... ) - else ( ... i,b,s,n ) + else ( ... n,s,b,t ) 4drop ( ... ) then ( ... ) then ( ... )