{"id":262,"date":"2015-07-21T22:22:45","date_gmt":"2015-07-22T02:22:45","guid":{"rendered":"http:\/\/72.167.111.237\/wpecsdump\/?page_id=262"},"modified":"2020-12-09T06:45:52","modified_gmt":"2020-12-09T11:45:52","slug":"the-micro-fsd","status":"publish","type":"page","link":"https:\/\/www.ecsdump.net\/?page_id=262","title":{"rendered":"The micro-FSD"},"content":{"rendered":"<p>This module contains the micro-FSD which is located between the partition bootsector and the actual data on the hard drive. The load segment was calculated in Phase 2 and for the Bochs drive image is 0x8800. The entry point is 8800:199C or 0x8999C with the registers (Bochs image) loaded as follows:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>\teax: 0x0000199C\n\tecx: 0x00007FBE\n\tedx: 0x00000080\n\tebx: 0x00000000\n\tesp: 0x00007C00\n\tebp: 0x00000000\n\tesi: 0xFFFF0046\n\tedi: 0x00000000\n\teflags 0x00000246\n\tIOPL=0 id vip vif ac vm rf nt of df IF tf sf ZF af PF cf<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Segment registers:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>cs:s=0x8800    ds:s=0x8800    ss:s=0x0000    es:s=0x07C0    fs:s=0x3000<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>This is somewhat irrelevant because es, ds, and ss will be set to cs (0x8800 in this example) and sp set to 0x5000.<\/p>\n<p>Items from previous loads:<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>If INT13 Ext functions are supported then 3000:0000, segment contain in fs, has 58333149h, stored as 49 31 33 58. If not the location is zero.<\/li>\n<li>The storage area contains the results of Phase 2 &#8212; (Bochs disk) 0x8803E 3F, 0, 0 0, 0, 0, 0, 0 or 0x000000000000003F.<\/li>\n<\/ul>\n<p>The JFS superblock procedure loads the super block and stores values at the following locations:<\/p>\n<p>&nbsp;<\/p>\n<div>superblock 8800:160C (0x8960C to 0x8980C)<br \/>\noffset 1858 to 185B (0x89858 to 0x89858)<br \/>\noffset 185C to 185F (0x8985C to 0x8985F)<\/div>\n<p>; module locations<br \/>\nft_cfiles dw 3<br \/>\nft_ldrseg dw 0<br \/>\nft_ldrlen dd 0<br \/>\nft_museg dw 0<br \/>\nft_mulen dd 0x5000<br \/>\nft_mfsseg dw 0<br \/>\nft_mfslen dd 0<br \/>\nft_ripseg dw 0<br \/>\nft_riplen dd 0x0<\/p>\n<p>; microFSD vector table<br \/>\nft_muOpen dd seg:1A9C<br \/>\nft_muRead dd seg:1BD4<br \/>\nft_muClose dd seg:1DAE<br \/>\nft_muTerminate dd seg:1DD4<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>88000\tjmp\tshort near ptr _entry  ;  Entry point from MBR code\n88002\tnop\n;  BIOS parameter block (<a href=\"https:\/\/en.wikipedia.org\/wiki\/BIOS_parameter_block\" data-internallinksmanager029f6b8e52c=\"4\" title=\"BPB\" target=\"_blank\" rel=\"noopener\">BPB<\/a>)\n88003\tdb    'IBM 4.50'    ; Partition creator\n8800B\tdb    0, 2    ; 0x0200 size of sector in bytes\n8800D\tdb    0\n8800E\tdb    0\n8800F\tdb    0\n88010\tdb    0\n88011\tdb    0\n88012\tdb    0\n88013\tdb    0\n88014\tdb    0\n88015\tdb   F8    ; media type - hard disk\n88016\tdb    0\n88017\tdb    0\n88018\tdb   3F, 0\t\t; BPB formatted geo: Sectors - 63\n8801A\tdb    20, 0\t\t; BPB formatted geo: Heads - 32\n8801C\tdb    3F, 0, 0 ,0\t; 0x0000003F hidden sectors\n88020\tdb    41, 12, 13, 0    ; 0x00131241 Big number of sectors\n88024\tdb    80    \t\t;  physical drive number\n88025\tdb    80    \t\t;  Boot drive letter\n88026\tdb    29    \t\t;  Ext-BPB signature\n88027\tdb    BD , 55,  9C, 69    ;  Partition serial number 0x699c55bd\n8802B\tdb    bochs, 0, 0, 0, 0, 0, 0    ; Partition label (11)\n88036\tdb    \"JFS     \"    ; Filesystem type (8)\n; Used as temp storage\n8803E\tdb    0, 0, 0, 0    ; absolute number of the start of the sectors\n88042\tdb    0, 0, 0, 0\n; <a href=\"https:\/\/www.ecsdump.net\/?page_id=884\" data-internallinksmanager029f6b8e52c=\"5\" title=\"DAP\" target=\"_blank\" rel=\"noopener\">DAP<\/a> : Disk Address Packet (16 bytes)\n88046\tdb    10\t\t; size of DAP = 16 = 10h\n88047\tdb    0\t\t\t; unused, should be zero\n88048\tdb    20\t\t; number of sectors to be read\n88049\tdb    0\t\t\t; unused, should be zero\n8804A\tdb    0, 0, 0, 0\t;segment:offset pointer to the memory buffer\n8804E\tdb    0, 0, 0, 0, 0, 0, 0, 0<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div>; eax: 0x00000001 ecx: 0x00007fbe edx: 0x00000080 ebx: 0x00000000<br \/>\n; esp: 0x00004ffe ebp: 0x00000000 esi: 0xffff160c edi: 0x00000040<br \/>\n; IOPL=0 id vip vif ac vm rf nt of df IF tf sf ZF af PF cf<\/div>\n<p>&nbsp;<\/p>\n<div>\n<pre>; readdrive\n;\n;  entry:\n;\tax contains number of sectors to read\n;       es segment for DAP structure\n;\tds segment for transfer buffer\n;\tsi offset for transfer buffer\n;       es: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\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\t; ds:0046\t\tsize of DAP - 16 bytes always\n\t\t; ds:0047\t\talways zero\n\t\t; ds:0048\t\tnumber of sectors to read\n\t\t; ds:0049\t\talways zero\n\t\t; ds:004A to 004D       segment:offset pointer transfer buffer\n\t\t; ds:004E to 0055\tabsolute number of the start of the sectors to be\n\t\t;                       read (1st sector of drive has number 0)\n\t\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         ; 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         ; 42h = function number for extended read\n\tmov\tdl, ds:24h      ; 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:                      ; 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; 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\n\tmov\tbx, 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;  Display address in hex\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\n\tmov\tbx, 7\n\tint\t10h\n\tretn\ndispchar\tendp<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>eax: 0x0000199c 6556<br \/>\necx: 0x00007fbe 32702<br \/>\nedx: 0x00000080 128<br \/>\nebx: 0x00000000 0<br \/>\nesp: 0x00007c00 31744<br \/>\nebp: 0x00000000 0<br \/>\nesi: 0xffff0046 -65466<br \/>\nedi: 0x00000000 0<br \/>\neip: 0x0000199c<br \/>\neflags 0x00000246<br \/>\nIOPL=0 id vip vif ac vm rf nt of df IF tf sf ZF af PF cf<\/p>\n<p>; cs:s=0x8800 ds:s=0x8800 ss:s=0x0000 es:s=0x07c0 fs:s=0x3000<\/p>\n<p>0x0008924a &lt;bogus+ 0&gt;: 0x03 0x00 0x00 0x10 0x00 0xae 0x00 0x00<br \/>\n0x00089252 &lt;bogus+ 8&gt;: 0x00 0x88 0x00 0x50 0x00 0x00 0x7c 0x00<br \/>\n0x0008925a &lt;bogus+ 16&gt;: 0xe9 0xea 0x00 0x00 0x00 0x00 0x00 0x00<br \/>\n0x00089262 &lt;bogus+ 24&gt;: 0x00 0x00 0x9c 0x1a 0x00 0x88<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>8924A ft_cfiles       dw 0x0003\n8924C ft_ldrseg       dw 0x1000\n8924E ft_ldrlen       dd 0xAE ; will vary with version of os2ldr used\n89252 ft_museg        dw 0x0000\n89254 ft_mulen        dd 0\n89258 ft_mfsseg       dw 0\n8925A ft_mfslen       dd 0\n8925E ft_ripseg       dw 0\n89260 ft_riplen       dd 0\n; microFSD vector table\n89264 ft_muOpen_OFF   \t\tdw 0\n89266 ft_muOpen_SEG   \t\tdw 0\n89268 ft_muRead_OFF   \t\tdw 0\n8926A ft_muRead_SEG   \t\tdw 0\n8926C ft_muClose_OFF  \t\tdw 0\n8926E ft_muClose_SEG  \t\tdw 0\n89270 ft_muTerminate_OFF \tdw 0\n89272 ft_muTerminate_SEG \tdw 0<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>This is the main entry point from Phase 2:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>(SEG:199C)\n_entry\tproc far\n\tpush\tcs\n\tpop\tax\n\tmov\tes, ax\t\t; swap cs to es\n\tmov\tds, ax\t\t; set ds to cs\n\t; setup\tstack\n\tcli\n\tmov\tss, ax\t\t; set ss to cs\n\tmov\tsp, 5000h\n\tsti\n\t; es \/ ds \/ ss\tset to entry cs\n\tcall\treadsuperblock\n\tmov\tax, 202h\n\tpush\tds\n\tpush\tax\n\tpush\tds\n\tmov\tsi, 2B2Fh\t; ALTF2ON.$ location\n\tpush\tsi\n\tmov\tax, cs\n\tmov\tword ptr cs:loc_899BC+3, ax\nloc_899BC:\n\tcall\tft_muOpen\n\tadd\tsp, 8\t\t; clean\tup the stack - post C function?\n\tor\tax, ax\n\tjnz\tshort MAIN_JMP_1 ; ?? zero return is good result\n\tmov\tal, 1\n\tmov\tds:byte_8AB2E, al\n\tmov\tax, cs\n\tmov\tword ptr cs:loc_899D3+3, ax\nloc_899D3:\n\tcall\tft_muClose\nMAIN_JMP_1:\n\tmov\tsi, 1D6h\t\t; os2boot file name\n\tmov\tdi, 7Ch\t\t\t; os2boot load address\n\tmov\tds:ft_mfsseg, di  ; miniFSD location\n\tcall\tLoadFile\n\ttest\tbx, 1\t\t; test if good load\n\tjz\tshort good_os2boot\n\tmov\tsi, 1274h\t; SYS1475: The file OS2BOOT cannot be found\n\tcall\tErrorHangSys    ; does not return\ngood_os2boot:\n\tmov\teax, ds:dword_88202\n\tmov\tds:ft_mfslen, eax    ; miniFSD length\n\tmov\tsi, 1CFh\t; os2ldr file name\n\tmov\tdi, 1000h\t; os2boot load address\n\tmov\tds:ft_ldrseg, di    ; os2ldr location\n\tcall\tLoadFile\n\ttest\tbx, 1\t\t; test if good load\n\tjz\tshort good_os2ldr\n\tmov\tsi, 12ABh\t; Missing OS2LDR\n\tcall\tErrorHangSys    ; does not return\ngood_os2ldr:\n\tmov\teax, ds:dword_88202\n\tmov\tds:ft_ldrlen, eax    ; os2ldr length\n\t; loading 0Fh to DispCopyInd stops display\n\t; of copyright message\n\tmov\tal, 0Fh\n\tmov\tds:DispCopyRInd, al\n\t; setup MicroFSD entry\n\tpush\tds\n\tpop\tax\n\tmov\tds:ft_museg, ax    ; MicroFSD location\n\tmov\teax, 5000h\n\tmov\tds:ft_mulen, eax    ; MicroFSD length\n\t; number of entries\n\tmov\tds:ft_cfiles, 3\n\t; sets up a function list\n\tmov\tds:ft_muOpen_SEG, ds\n\tmov\tds:ft_muOpen_OFF, 1A9Ch\t; ds:1A9C\n\tmov\tds:ft_muRead_SEG, ds\n\tmov\tds:ft_muRead_OFF, 1BD4h\t; ds:1BD4\n\tmov\tds:ft_muClose_SEG, ds\n\tmov\tds:ft_muClose_OFF, 1DAEh ; ds:1DAE\n\tmov\tds:ft_muTerminate_SEG, ds\n\tmov\tds:ft_muTerminate_OFF, 1DAEh ; ds:1DD4\n\tmov\tds:ft_ripseg, 0\n\tmov\tds:ft_riplen, 0\n\tpush\tds\n\tpush\tcs\n\tpop\tds\n\tmov\teax, dword ptr ds:aJfs+8\n\tmov\tds:dword_8801C,\teax\n\tpop\tds\n\tassume ds:nothing\n\txor\tdi, di\t\t; zero di\n\tmov\tes:[di], eax\n\tmov\tdl, ds:24h\n\tmov\tdh, dl\n\tmov\tds:24h,\tdx\n\tmov\tdh, 14h\n\tmov\tsi, 0Bh\n\tpush\tds\n\tpop\tes\n\tmov\tdi, 124Ah\n\tmov\tax, ds:124Ch\n\tpush\tax\n\txor\tax, ax\n\tpush\tax\n\tretf\t; Should be a return which enters os2ldr\n_entry\tendp<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>readsuperblock  proc near\n\tmov\tsi, 160Ch    ; 8800:160C buffer\n\tmov\tax, 1\t\t; read 1 sector\n\tmov\tedi, 40h      ; offset from beginning of partition\n\tmov\tebx, 0         ; for read\n\t; read 1 sector from offset of partition 0x40 (64) or 32,768\n\t; from the IBM docs this would be the superblock and it gets\n\t; read into memory at offset 160C buffer\n\t; see openJFS -- jfs_superblock.h\n\tcall\treaddrive      ; load superblock to 0x8960C\n\tmov\teax, ds:161Ch\n\tbsf\tecx, eax\n\tmov\tds:1942h, cx     ; 0x89942\n\tmov\tedx, ds:163Ch\n\tand\tedx, 0FF000000h\n\tshr\tedx, 18h\n\tmov\teax, ds:1640h\n\tshld\tedx, eax, cl\n\tshl\teax, cl\n\tmov\tds:1858h, eax         ; 0x89858\n\tmov\tds:185Ch, edx         ; 0x8985C\n\tmov\tdword ptr ds:23Eh, 2  ; 0x8823E\n\tpush\tbp\n\tmov\tbp, sp\n\txor\tecx, ecx\n\tmov\tdi, 3D45h\n\tcall\tsub_8AA59\n\tmov\tcl, al\n\tmov\tch, 0\n\tpush\tcx\n\tmov\tdi, 1509h\n\tcall\tsub_8AA59\n\tmov\tbx, 1\n\tpop\tcx\n\tcmp\tcl, al\n\tjg\tshort loc_8AA55\n\tmov\tsi, 3D45h\n\tmov\tdi, 1509h\n\tmov\tbx, 1\n\trepe cmpsb\n\tor\tcl, cl\n\tjnz\tshort loc_8AA55\n\tcmp\tbyte ptr es:[di], 5Ch ;\t'\\'\n\tjz\tshort loc_8AA3E\n\tcmp\tbyte ptr es:[di], 0\n\tjnz\tshort loc_8AA55\nloc_8AA3E:\n\tmov\tal, [si-1]\n\tcmp\tal, es:[di-1]\n\tjnz\tshort loc_8AA55\n\tmov\tdi, si\n\tmov\tal, 5Ch\t; '\\'\n\tstosb\n\tmov\tds:14EFh, di\n\txor\tax, ax\n\tstosb\n\txor\tbx, bx\nloc_8AA55:\n\tmov\tax, bx\n\tpop\tbp\n\tretn\nreadsuperblock  endp<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This module contains the micro-FSD which is located between the partition bootsector and the actual data on the hard drive. The load segment was calculated in Phase 2 and for the Bochs drive image is 0x8800. The entry point is 8800:199C or 0x8999C with the registers (Bochs image) loaded as follows: &nbsp; eax: 0x0000199C ecx:&hellip;<\/p>\n<p><a class=\"more-link\" href=\"https:\/\/www.ecsdump.net\/?page_id=262\" title=\"Continue reading &lsquo;The micro-FSD&rsquo;\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":798,"menu_order":4,"comment_status":"open","ping_status":"open","template":"page-templates\/full-width.php","meta":{"footnotes":""},"categories":[4],"tags":[20,103,28],"wf_page_folders":[104],"class_list":["post-262","page","type-page","status-publish","hentry","category-boot-process","tag-boot","tag-micro-fsd","tag-os2"],"jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/262","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=262"}],"version-history":[{"count":0,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/262\/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=262"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=262"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=262"},{"taxonomy":"wf_page_folders","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fwf_page_folders&post=262"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}