{"id":259,"date":"2015-07-21T22:19:44","date_gmt":"2015-07-22T02:19:44","guid":{"rendered":"http:\/\/72.167.111.237\/wpecsdump\/?page_id=259"},"modified":"2020-12-09T06:42:00","modified_gmt":"2020-12-09T11:42:00","slug":"partition-bpb-disassembled","status":"publish","type":"page","link":"https:\/\/www.ecsdump.net\/?page_id=259","title":{"rendered":"Partition BPB Disassembled"},"content":{"rendered":"<p>BIOS parameter block (<a href=\"https:\/\/en.wikipedia.org\/wiki\/BIOS_parameter_block\" data-internallinksmanager029f6b8e52c=\"4\" title=\"BPB\" target=\"_blank\" rel=\"noopener\">BPB<\/a>) is a variant record embedded within the boot block (block zero) of a disc volume. In the example below the BPB is located from 0x7C0B to 0x7C36. The references I used, <a class=\"ext\" href=\"http:\/\/homepages.tesco.net\/J.deBoynePollard\/FGA\/bios-parameter-block.html\">bios-parameter-block<\/a> and <a class=\"ext\" href=\"http:\/\/www.dfsee.com\/\">DFSee<\/a>.<\/p>\n<p>Entry is made at 0x7C00 followed by a jump to _entry. After the stack is set up INT 12 is called to find the top of low memory (640K). Next, 54h (84 dec) is subtracted, and AND with 0xFFF0 then shifted left (6) to get the segment for the next module load (micro-FSD). For the Bochs example image the result is 0x8800. A load of BPB+31 sectors is loaded at the calculated segment and offset 0x0000 and the temp storage area is moved to this area (7C3E &#8211; 7C45). This load contains the instructions to continue the system load and the micro-FSD.<\/p>\n<p>During the drive read and error will result in <a href=\"https:\/\/www.ecsdump.net\/?page_id=884\" data-internallinksmanager029f6b8e52c=\"5\" title=\"DAP\" target=\"_blank\" rel=\"noopener\">DAP<\/a> information being displayed and a SYS02027 message, the system will then hang. The error sequence is from the readdrive procedure which is also used executing the micro-FSD loading code.<\/p>\n<p>A check of the calculated segment and offset 0x0200 is made for 0x1961 signature. If the signature is found and return from function is executed which will result in execution continuing at the calculated load segment and offset 0x199C (Bochs image 8800:199C or 0x8999C). If the signature is now found, a &#8220;Invalid code for JFS&#8221; error and some address information will be displayed and the system will hang.<\/p>\n<p>&nbsp;<\/p>\n<div><em><strong>NOTE:<\/strong> Getting a &#8220;Invalid code for JFS&#8221; error could be cleared up with a sysinstx.com on the boot drive or by using DFSee.<\/em><\/div>\n<p>On entry a register dump and these might not be set values (based on Bochs image):<\/p>\n<p>eax: 0x00000000 ecx: 0x00007fbe &#8212; MBR info location edx: 0x00000080 &#8212; Drive number<br \/>\nebx: 0x00007fbe &#8212; MBR info location esi: 0xffff7fbe &#8212; MBR info location<br \/>\nedi: 0x00080005 eip: 0x00007c00<\/p>\n<p>eflags 0x00000246<br \/>\ncs:s=0x0000 ds:s=0x0000 ss:s=0x0030 es:s=0x0000<br \/>\nfs:s=0x3000 &#8212; location of INT 13 Ext result<\/p>\n<p>The Extended Boot structure is as follows:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>struct Extended_Boot {\n\tunsigned char Boot_jmp[3];\n\tunsigned char Boot_OEM[8];\n\tstruct Extended_BPB Boot_BPB;\n\tunsigned char Boot_DriveNumber;\n\tunsigned char Boot_CurrentHead;\n\tunsigned char Boot_Sig = 41; \/* Indicate Extended Boot *\/\n\tunsigned char Boot_Serial[4];\n\tunsigned char Boot_Vol_Label[11];\n\tunsigned char Boot_System_ID[8];\n};<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Where&nbsp;<\/p>\n<div>Boot_Serial<\/p>\n<div>\n<div>is the 32-bit binary volume serial number for the media. Boot_System_ID<br \/>\nis an 8-byte name written when the media is formatted. It is used by FSDs to identify their media but need not be the same as the name the FSD exports via FS_NAME and is NOT the name users employ to refer to the FSD. (They may, however, be the same names). Boot_Vol_Label<br \/>\nis the 11-byte ASCII label of the disk\/diskette volume. FAT file systems must ALWAYS use the volume label in the root directory for compatibility reasons. An FSD may use the one in the boot sector.<\/div>\n<\/div>\n<\/div>\n<p>&nbsp;<\/p>\n<div>The extended BPB structure is a super-set of the conventional BPB structure, as follows:<\/div>\n<p>&nbsp;<\/p>\n<div>\n<pre>\t  struct Extended_BPB {    unsigned short BytePerSector;\n\t\t  unsigned char SectorPerCluster;\n\t\t  unsigned short ReservedSectors;\n\t\t  unsigned char NumberOfFats;\n\t\t  unsigned short RootEntries;\n\t\t  unsigned short TotalSectors;\n\t\t  unsigned char MediaDescriptor;\n\t\t  unsigned short SectorsPerFat;\n\t\t  unsigned short SectorsPerTrack;\n\t\t  unsigned short Heads;\n\t\t  unsigned long HiddenSectors;\n\t\t  unsigned long Ext_TotalSectors;\n\t  };<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>7C00\tjmp\tshort near ptr _entry  ;  Entry point from MBR code\n7C02\tnop\n;  BIOS parameter block (BPB)\n7C03\tdb    'IBM 4.50'    ; Partition creator\n7C0B\tdb    0, 2    ; 0x0200 size of sector in bytes\n7C0D\tdb    0\n7C0E\tdb    0\n7C0F\tdb    0\n7C10\tdb    0\n7C11\tdb    0\n7C12\tdb    0\n7C13\tdb    0\n7C14\tdb    0\n7C15\tdb   F8    ; media type - hard disk\n7C16\tdb    0\n7C17\tdb    0\n7C18\tdb   3F, 0\t\t; BPB formatted geo: Sectors - 63\n7C1A\tdb    20, 0\t\t; BPB formatted geo: Heads - 32\n7C1C\tdb    3F, 0, 0 ,0\t; 0x0000003F hidden sectors\n7C20\tdb    41, 12, 13, 0    ; 0x00131241 Big number of sectors\n7C24\tdb    80    \t\t;  physical drive number\n7C25\tdb    80    \t\t;  Boot drive letter\n7C26\tdb    29    \t\t;  Ext-BPB signature\n7C27\tdb    BD , 55,  9C, 69    ;  Partition serial number 0x699c55bd\n7C2B\tdb    bochs, 0, 0, 0, 0, 0, 0    ; Partition label (11)\n7C36\tdb    \"JFS     \"    ; Filesystem type (8)\n; Used as temp storage\n7C3E\tdb    0, 0, 0, 0    ; absolute number of the start of the sectors\n7C42\tdb    0, 0, 0, 0\n; DAP : Disk Address Packet (16 bytes)\n7C46\tdb    10\t\t; size of DAP = 16 = 10h\n7C47\tdb    0\t\t\t; unused, should be zero\n7C48\tdb    20\t\t; number of sectors to be read\n7C49\tdb    0\t\t\t; unused, should be zero\n7C4A\tdb    0, 0, 0, 0\t;segment:offset pointer to the memory buffer\n7C4E\tdb    0, 0, 0, 0, 0, 0, 0, 0<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>_entry    proc far\n\tcli\t\t\t; Clear Interrupt Flag\n\txor\tax, ax\t\t; zero ax\n\tmov\tss, ax\t\t; set SS to 0000\n\tmov\tsp, 7C00h    \t; set stack pointer\n\tsti\t\t\t; Set Interrupt Flag\n\tmov\tbx, 7C0h\n\tmov\tes, bx\t\t; 7C0 to es\n\tsti\t\t\t; Set Interrupt Flag\n\t; ax == 0  ss == 0  sp == 7C0  es == 7C0\n\t; Find the top of continuous low memory (640K)\n\t; subtract 54h (84 dec) or 84K\n\t; clear lower 4 bits\n\t; shift left 6 bits and move to ds\n\t; this will be the segment address for os2boot loading\n\t; Returns 27Fh - 639 is returned from Bochs and final ds == 0x8800\n\tint\t12h\t\t; MEMORY SIZE - LOW MEM Return: AX = number of contiguous 1K blocks of memory\n\tsub\tax, 54h\t\t; subtract 54h -- 84 dec\n\tand\tax, 0FFF0h\t; 1111111111110000b - results in 220h\n\tshl\tax, 6\t\t; Shift\tLogical\tLeft\n\tmov\tds, ax\n\txor\tedi, edi\t\t; zero edi\n\txor\tebx, ebx\t\t; zero edx\n\tmov\teax, es:1Ch\t; load eax 0x1C  (Bochs drive 0x0000003F) hidden sectors\n\t; add start of partition to readdrive storage\n\tadd\tes:3Eh,\teax\n\tadc\tes:42h,\tebx\n\tpush\tds\t\t; buffer segment\n\tmov\tax, 20h\t\t; number sectors to read\n\txor\tsi, si\t\t; buffer offset\n\t; Bochs drive:\n\t; eax: 0x00000020   ecx: 0x00007fbe  edx: 0x00000080  ebx: 0x00000000   esp: 0x00007bfe\n\t; esi: 0xffff0000   edi: 0x00000000\n\t; cs:s=0x0000  ds:s=0x8800  ss:s=0x0000  es:s=0x07c0  fs:s=0x3000\n\tcall\treaddrive\n\tpop\tds\n\t; Bochs drive:\n\t; if reados2boot returns from goodread, registers:\n\t; eax: 0x00000000  ecx: 0x00007fbe  edx: 0x00000080  ebx: 0x00000000  esp: 0x00007c00\n\t; ebp: 0x00000000  esi: 0xffff0046\n\t; cs:s=0x0000  ds:s=0x8800  ss:s=0x0000  es:s=0x07c0  fs:s=0x3000\n\t; stack is empty\n\t; move from part. boot data to Phase 3 data area\n\tmov\teax, es:3Eh\n\tmov\tds:3Eh,\teax\t; Bochs image move 0x7C3E to 0x8803E\n\tmov\teax, es:42h\n\tmov\tds:42h,\teax\t; Bochs image move 0x7C42 to 0x88042\n\tmov\tal, es:24h\n\tmov\tds:24h,\tal\t; Bochs image move 0x7C24 to 0x88024\n\t; check for 1961h at 8800:0200 (0x88200)\n\tcmp\tword ptr ds:200h, 1961h\n\tjz\tshort  _goodload\n\tmov\tax, 7C0h\n\tmov\tds, ax\n\tmov\tax, ds:200h\t; move 7E00 to ax  == 0xb8fa\n\tmov\tsi, 0C8h\t\t; *** display - \"Invalid code for JFS\" ***\n\tcall\tdisplayerr\n_goodload:\n\tpush\tds\t\t; segment entry -- calc from previous\n\tmov\tax, 199Ch\t; Offset\n\tpush\tax\t\t; 8800:199C (0x8999C) for Bochs drive\n\tretf\t\t\t; Return Far from Procedure\n_entry    endp<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>(0x7CC8)    InvalidCode\tdb 'Invalid code for JFS ',0\n(0x7CDE)    Sys02027\tdb '- SYS02027 - ',0<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>;On entry the Bochs registers are:\n; eax: 0x00000020   ecx: 0x00007fbe  edx: 0x00000080  ebx: 0x00000000   esp: 0x00007bfe\n; esi: 0xffff0000   edi: 0x00000000\n; cs:s=0x0000  ds:s=0x8800  ss:s=0x0000  es:s=0x07c0  fs:s=0x3000\n; readdrive\n;\n;  entry:\n;\tax contains number of sectors to read\n;\tes segment for DAP structure\n;\tds segment for transfer buffer\n;\tsi offset for transfer buffer\n;\tes:003E + 4 and es:0042 + 4 absolute number start sectors to read\n;\tes:0024 drive index\n;\tdi (L) and bx (H) contain offset to absolute start for begin read\nreaddrive  proc near\n\tpush\tds\t\t; save ds and dx\n\tpush\tdx\n\tmov\tdx, ds\n\tpush\tes\n\tpop\tds\t\t; set ds to entry es value\n\t; DAP : Disk Address Packet (16 bytes)\n\t; offset range \tsize \tdescription\n\t; 00h \t\t1 byte \tsize of DAP = 16 = 10h\n\t; 01h \t\t1 byte \tunused, should be zero\n\t; 02h \t\t1 byte \tnumber of sectors to be read, 0..127 (= 7Fh)\n\t; 03h \t\t1 byte \tunused, should be zero\n\t; 04h..07h    4 bytes \tsegment:offset pointer to the memory buffer\n\t;\t\t\tto which sectors will be transferred\n\t; 08h..0Fh    8 bytes \tabsolute number of the start of the sectors to be read\n\t; This routine DAP structure:\n\t; ds:0046\t\tsize of DAP - 16 bytes always\n\t; ds:0047\t\talways zero\n\t; ds:0048\t\tnumber of sectors to read\n\t; ds:0049\t\talways zero\n\t; ds:004A to 004D       segment:offset pointer transfer buffer\n\t; ds:004E to 0055\tabsolute number of the start of the sectors to be\n\t;                       read (1st sector of drive has number 0)\n\t; Load DAP\n\tmov\tds:48h,\tax\t; number of sectors to read, ax contains on entry\n\tmov\tds:4Ch,\tdx\t; Buffer segment\n\tmov\tds:4Ah,\tsi\t; Buffer offset\n\tmov\tsi, 46h         \t; DAP offset\n\tmov\teax, ds:3Eh\t; move sector read start from storage area\n\tmov\tds:4Eh,\teax\t; ds:003E to ds:0055 to DAP\n\tmov\teax, ds:42h\n\tmov\tds:52h,\teax\n\tadd\tds:4Eh,\tedi\n\tadc\tds:52h,\tebx\n\t; DAP located at ds:0046\n\tmov\tah, 42h         \t; 42h = function number for extended read\n\tmov\tdl, ds:24h      \t; drive index\n\tmov\tal, 0\n\tint\t13h\t\t; cf  Set On Error, Clear If No Error\n\t\t\t\t; ah  Return Code\n\tjnb\tshort goodread\n\tor\tah, ah\n\tjnz\tshort readerror\ngoodread:\n\tpop\tdx\t\t; restore entry dx and ds before returning\n\tpop\tds\n\tretn\nreaderror:\t\t\t; display some DAP info\n\tpush\tax\n\tmov\teax, ds:52h\n\tshr\teax, 10h\n\tcall\tdispaddress\n\tmov\teax, ds:52h\n\tcall\tdispaddress\n\tmov\teax, ds:4Eh\n\tshr\teax, 10h\n\tcall\tdispaddress\n\tmov\teax, ds:4Eh\n\tcall\tdispaddress\n\tmov\tax, ds:48h\n\tshl\teax, 10h\n\tpop\tax\n\tmov\tal, dl\n\tmov\tsi, 0DEh\t\t; SYS02027  message\n\tcall\t$+3\t\t; really a jump to displayerr - never returns\nreaddrive  endp\n; displayerr\n;  Display error message pointed to by ds:(e)si and address\n;  then hang the system\ndisplayerr\tproc near\n\tcld\n\tpush\teax\n_dispnextchar:\n\tlodsb\t\t\t; Load byte at address DS:(E)SI into AL\n\ttest\tal, 0FFh\n\tjz\tshort   _endmessage\n\tmov\tah, 0Eh\t\t; int10 teletype output\n\tmov\tbx, 7\t\t; page 0 - color 7\n\tint\t10h\n\tjmp\tshort _dispnextchar\n_endmessage:\n\tsti\n\tpop\teax\n\tpush\teax\n\tand\teax, 0FFFF0000h\n\tshr\teax, 10h\n\tcall\tdispaddress\n\tmov\tal, 3Ah\n\tmov\tah, 0Eh\n\tmov\tbx, 7\n\tint\t10h\n\tpop\teax\n\tcall\tdispaddress\n_hangsystem:\n\tjmp\tshort   _hangsystem\ndisplayerr\tendp\n; dispaddress\n;  Entry - address (16 bit) in ax\n;  Display address in hex on page 0\n dispaddress\tproc near\n\tpush\tax\n\tmov\tal, ah\n\tand\tal, 0F0h\n\tmov\tcl, 4\n\tshr\tal, cl\n\tcall\tdispchar\n\tpop\tax\n\tpush\tax\n\tmov\tal, ah\n\tand\tal, 0Fh\n\tcall\tdispchar\n\tpop\tax\n\tpush\tax\n\tand\tal, 0F0h\n\tmov\tcl, 4\n\tshr\tal, cl\n\tcall\tdispchar\n\tpop\tax\n\tpush\tax\n\tand\tal, 0Fh\n\tcall\tdispchar\n\tpop\tax\n\tretn\ndispaddress  endp\n; dispchar\n;  Output char from dispaddress\ndispchar\tproc near\n\tadd\tal, 30h\n\tcmp\tal, 39h\n\tjle\tshort   _dispchar1\n\tadd\tal, 7\n_dispchar1:\n\tmov\tah, 0Eh\t; int10 teletype output\n\tmov\tbx, 7\t; page 0 - color 7\n\tint\t10h\n\tretn\ndispchar\tendp<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>Os2ldr\tdb 'OS2LDR',0\nOs2boot\tdb 'OS2BOOT',0\nshtemenko   db '(c) P.Shtemenko 2002,2004',0\n\tdb    0\n\tdb    0\n\tdb    0\n\tdb    0\n\tdb    0\n\tdb    0\n\tdw 0AA55h<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>BIOS parameter block (BPB) is a variant record embedded within the boot block (block zero) of a disc volume. In the example below the BPB is located from 0x7C0B to 0x7C36. The references I used, bios-parameter-block and DFSee. Entry is made at 0x7C00 followed by a jump to _entry. After the stack is set up&hellip;<\/p>\n<p><a class=\"more-link\" href=\"https:\/\/www.ecsdump.net\/?page_id=259\" title=\"Continue reading &lsquo;Partition BPB Disassembled&rsquo;\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":798,"menu_order":3,"comment_status":"open","ping_status":"open","template":"page-templates\/full-width.php","meta":{"footnotes":""},"categories":[4],"tags":[20,98,102],"wf_page_folders":[104],"class_list":["post-259","page","type-page","status-publish","hentry","category-boot-process","tag-boot","tag-boot-sector","tag-bpb"],"jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/259","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=259"}],"version-history":[{"count":0,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/259\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/798"}],"wp:attachment":[{"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=259"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=259"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=259"},{"taxonomy":"wf_page_folders","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fwf_page_folders&post=259"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}