{"id":257,"date":"2015-07-21T22:15:24","date_gmt":"2015-07-22T02:15:24","guid":{"rendered":"http:\/\/72.167.111.237\/wpecsdump\/?page_id=257"},"modified":"2020-12-09T06:39:20","modified_gmt":"2020-12-09T11:39:20","slug":"lvm-mbr-disassembled","status":"publish","type":"page","link":"https:\/\/www.ecsdump.net\/?page_id=257","title":{"rendered":"LVM MBR Disassembled"},"content":{"rendered":"<p>Loaded at 7C00h, setup stack and copy block from 7C00 to 7E00h. Push 7E20h on the stack and return near which will begin execution at 7E20h. This is the initial code loaded at 07C0:0000 and the disassembled code relocated at 07E0:0000 continues below.<\/p>\n<p>After relocation the entry is at 7E20, I left out the 7E00 to 7E1F code which is not used. I am really only interested in the basic follow and the loaded and follow-on module, so some of the commenting could be better. In general, a Boot Manager partition is looked for and a simple consistency check is done on the MBR.<\/p>\n<p>If you see below a check is made to verify INT 13 Extensions API support (see <a class=\"missingpage\" title=\"Create this page\" href=\"http:\/\/www.mgreene.org\/wikka\/CheckINT13Ext\/edit\">CheckINT13Ext<\/a>). The result is stored at 3000:0000, if supported 58333149h is stored if not 0 is stored. This value is used later.<\/p>\n<p><a class=\"missingpage\" title=\"Create this page\" href=\"http:\/\/www.mgreene.org\/wikka\/ReadDrive\/edit\">ReadDrive<\/a> procedure is used to load the second drive without using the INT 13 Extensions API, but is used later to load the partition boot information using INT 13 Extensions API.<\/p>\n<p>Things for my own note, there are 3 possible error messages while processing the LVM MBR: SYS01462, SYS01463, and SYS01464. Also, the drives look like they must support INT 13 Extensions API which should not be a problem now days.<\/p>\n<p>The partition boot information is loaded at 7C00 and execution is continued.<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>(7C00h)\n_entry\t\tproc near\n\t; disable interupts\n\tcli\n\t; setup stack\n\tmov\tax, 30h\n\tmov\tss, ax\n\tmov\tsp, 100h  ; decimal 256\n\t; enable interupts\n\tsti\n\t; move 7C00 to 7E00 +512\n\tcld\n\txor\tax, ax     ; Zero out the Accumulator\n\tmov\tds, ax     ; Zero-out Data Segment\n\tmov\tes, ax     ; Zero-out Extra Segment\n\tmov\tsi, 7C00h  ; Copy from here...\n\tmov\tdi, 7E00h  ; copy to here: 0000:7E00\n\tmov\tcx, 200h   ; 200h (512 words) count\n\trep movsw\n\t; push return addr 7E20 and execute return\n\tpush\t7E20h\n\tretn\n_entry\t\tendp<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>After the code is moved from 0000:7C00 to 0000:7E00 the entry point is 0000:7E20.<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>(7E20)\n_relocentry     proc near\n\tmov     si, 7EFAh       ; si point to SYS01462 message start\n\tmov     bx, 7FBEh       ; bx set to first partition info location\n; *** Check for Boot Manager\n; read each MBR record and check if it is type Boot Manager (0x0A).\nbootman00:\n\tcmp     byte ptr [bx+4], 0Ah ; cmp part type 11 (0Ah) BootManager\n\tjz      short checktype      ; jump if Boot Manager partition found\n\tadd     bx, 10h              ; setup to read next partition entry\n\tcmp     bx, 7FFEh            ; check for sig - end of MBR if not get next\n\tjl      short bootman00\n\txor     ax, ax               ; zero ax\n\tint     13h                  ; DISK - RESET DISK SYSTEM\n\t; DISK - GET DRIVE PARAMETERS (PC,XT286,CONV,PS,ESDI,SCSI)\n\t; AH = 08h\n\t; DL = drive (bit 7 set for hard disk)\n\t; Return:CF set on error\n\t; AH = status (07h) (see #0211)\n\t; CF clear if successful\n\t; AH = 00h\n\t; AL = 00h on at least some BIOSes\n\t; BL = drive type (AT\/PS2 floppies only) (see #0219)\n\t; CH = low eight bits of maximum cylinder number\n\t; CL = maximum sector number (bits 5-0)\n\t; high two bits of maximum cylinder number (bits 7-6)\n\t; DH = maximum head number\n\t; DL = number of drives\n\t; ES:DI -&gt; drive parameter table (floppies only)\n\t; check for drive #2\n\tmov     ah, 8\n\tmov     dl, 81h ; drive 2\n\tint     13h\n\tjb      short checktype ;  jump no 2nd drive\n\t; read 2nd drive MBR\n\tmov     cx, 7FB4h\n\tmov     dl, 81h\n\tcall    ReadDrive\n\tor      ah, ah\n\tjnz     short checktype   ; jump if read error\n\tcmp     word ptr ds:7DFEh, 0AA55h  ; check signature\n\tjnz     short checktype    ; jump not valid MBR signature\n\tmov     bx, 7DBEh ; set start 2nd drive MBR info\n\t; Check for Boot Manager on 2nd drive\nbootman01:\n\tcmp     byte ptr [bx+4], 0Ah\n\tjnz     short bootman02\n\t; the following get executed if a 0Ah found on 2nd drive\n\tmov     dl, 81h    ; second drive 81h in dl\n\tmov     cx, bx      ; bx - location of 0Ah partition info\n\tjmp     short extcheck2\nbootman02:\n\tadd     bx, 10h\n\tcmp     bx, 7DFEh\n\tjl      short bootman01\n; *** Check for bootable partition\n; get here if boot manager part found on 1st drive,  no second drive, and falls through\n; no boot manager found on second drive\nchecktype:\n\tmov     bx, 7FBEh  ; load _bootind partition 1\n\txor     cx, cx  ; zero cx\n; seems to just run through the MBR and ensure it is somewhat correct\nchecktype1:\n\tcmp     byte ptr [bx], 80h ; is it bootable?\n\tjnz     short checktype2   ; jump if not bootable\n\tor      cx, cx\n\tjnz     short DispMsgEntry ; Not zero display SYS01462 error and hang\n\tmov     cx, bx\n\tjmp     short checktype3\nchecktype2:\n\tcmp     byte ptr [bx], 0 ; is it 0 (not-bootable) - so if not 80h or 0 then unknown _bootind\n\tjnz     short DispMsgEntry ; Not zero display SYS01462 error and hang\nchecktype3:\n\tadd     bx, 10h ; increment to next partition record\n\tcmp     bx, 7FFEh ; at the end of MBR - check signature\n\tjl      short checktype1\n\tor      cx, cx\n\tjnz     short extcheck1\n\tint     18h        ; None were bootable, so start ROM-BASIC many\n\t\t\t; BIOS simply display \"PRESS A KEY TO REBOOT\"\n\t\t\t; when an Interrupt 18h is executed.\nextcheck1:\n\tmov     dl, 80h    ; first drive\n; at this point dl contains drive number 80h or 81h\nextcheck2:\n\tpusha                 ; PUSH AX, CX, DX, BX, SP, BP, SI and DI\n\tcall    CheckINT13Ext\n\tpopa                  ; POP  AX, CX, DX, BX, SP, BP, SI and DI\n\tpush    dx\n\tpush    cx\n\tcall    ReadDrive\n\tjz      short vbr00        ; jump no error\n\tmov     si, 7F0Fh          ; SYS01463 Message\n\tjmp     short DispMsgEntry ; Not zero display error and hang\nvbr00:\n\tmov     si, 7F24h                 ; SYS01464 Message\n\tcmp     ds:SigEnd, 0AA55h    ; compare to end block signature\n\tjnz     short DispMsgEntry     ; Not zero display error and hang\n\tpop     si\t; seems to hold MBR pointer\n\tpop     dx\t; boot drive number\n\tjmp     far ptr 0000:7C00h    ; ** jump 0000:7C00 **\n_relocentry     endp\n; IBM\/MS INT 13 Extensions - INSTALLATION CHECK\n; AH = 41h\n; BX = 55AAh\n; DL = drive (80h-FFh)\n; Return:CF set on error (extensions not supported)\n; AH = 01h (invalid function)\n; CF clear if successful\n; BX = AA55h if installed\n; AH = major version of extensions\n;   01h = 1.x\n;   20h = 2.0 \/ EDD-1.0\n;   21h = 2.1 \/ EDD-1.1\n;   30h = EDD-3.0\n; AL = internal use\n; CX = API subset support bitmap (see #0248)\n; DH = extension version (v2.0+ ??? -- not present in 1.x)\n; Note: The Phoenix Enhanced Disk Drive Specification v1.0 uses version 2.0 of the INT 13 Extensions API\n;\n; See Also: AH=42h\"INT 13 Ext\" - AH=48h\"INT 13 Ext\"\n;\n; Bitfields for IBM\/MS INT 13 Extensions API support bitmap:\n;\n; Bit(s)  Description     (Table 0248)\n;   0      extended disk access functions (AH=42h-44h,47h,48h) supported\n;   1      removable drive controller functions (AH=45h,46h,48h,49h,INT 15\/AH=52h)\n;           supported\n;   2      enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported.\n;  Extended drive parameter table is valid (see #0250,#0255)\n;   3-15   reserved (0)\n;\n; NOTE: From : http:\/\/lrs.uni-passau.de\/support\/doc\/interrupt-57\/RB-0668.HTM\n; checks for extended int 13 capability -\n; Exit if supported  3000:0000   move  58333149h\n; not supported mov 0\n; * dl contains drive number on entry\n(7EBA)\nCheckINT13Ext   proc near\n\tmov     ah, 41h\n\tmov     bx, 55AAh\n\tint     13h\n\tjb      short NoINT13Ext        ; jump to NoINT13Ext is not supported\n\tcmp     bx, 0AA55h              ; AA55h if installed INT 13 Extensions API\n\tjnz     short NoINT13Ext\n\tcmp     ah, 21h                 ; major version of extensions 21h = 2.1 \/ EDD-1.1\n\tjb      short NoINT13Ext\n\ttest    cl, 1                   ; Test if extended Disk Access functions supported\n\tjz      short NoINT13Ext\n\tmov     eax, 58333149h\n\tjmp     short INT13Continue\nNoINT13Ext:\n\txor     ax, ax    ; zero ax if ext 13 not supported\nINT13Continue:\n\tpush    3000h    ; store eax at 3000:0000\n\tpop     fs\n\tmov     fs:0, eax\n\tretn\nCheckINT13Ext   endp<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>There are 3 possible error messages while processing the LVM MBR: SYS01462, SYS01463, and SYS01464:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>***** DISPLAY MESSAGE LOOP *****\n(7EE8)\nDispMsgEntry:\n\txor     bx, bx\t; zero bx\n\tjmp     short DispMsg\nDispNext:\n\tint     10h\nDispMsg:\n\tmov     ah, 0Eh\n\tlodsb\t\t; get char of message\n\tor      al, al\t; check if end\n\tjnz     short DispNext\n\tsti\nHangLoop:\n\tjmp     short HangLoop\n; The following boot message information is from Bob Eager,\n; Tavi Systems page http:\/\/www.tavi.co.uk\/os2pages\/boot.html:\n; SYS01462\n; The partition table on the startup drive is incorrect. Generally, this\n; means either that more than one partition is marked active, or one of\n; the partitions has a status byte with a value other than 00H or 80H,\n; which are the only legal values.\n7EF8                 db  12h\n7EF9                 db    0\n7EFA _SYS01462       db 'OS\/2 !! SYS01462',0Dh,0Ah,0\n; SYS01463\n; The operating system cannot be loaded from the startup drive. This is\n; caused by a disk read error, while reading the boot sector of the\n; active partition\n7F0D                 db  12h\n7F0E                 db    0\n7F0F _SYS01463       db 'OS\/2 !! SYS01463',0Dh,0Ah,0\n; SYS01464\n; The operating system is missing from the startup drive. A valid boot\n; sector for a partition should contain the values 055H and 0AAH in its\n; last two bytes, in that order. This is a simple validation check,\n; intended to prevent attempts to boot from a corrupt or unformatted\n; partition. This message is generated if the validation check for\n; these two bytes fails.\n7F22                 db  12h\n7F23                 db    0\n7F24 _SYS01464       db 'OS\/2 !! SYS01464',0Dh,0Ah,0<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>ReadDrive procedure loads MBR of the second drive and the boot record of the botable partition:<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>; On entry:\n;    DL == drive\n;    CX == location of Track + Sector to read\n;    location 3000:0000 == 49h ext read supported else old 0 - 1023 read\nReadDrive       proc near\n\tmov     bx, cx\n\tmov     di, 5\n\t ; see INT13Ext storage 3000:0000\n\tpush    3000h\n\tpop     fs\n\tcmp     byte ptr fs:0, 49h\n\tjz      short ExtRead    ; equals 49h if ext supported\n\t; CX contains both the cylinder number (10 bits, possible\n\t; values are 0 to 1023) and the sector number (6 bits, possible values are 1 to 63):\n\tmov     cx, [bx+2]\n\t; Head\n\tmov     dh, [bx+1]\n\t; (ES):BX = Memory Buffer\n\tmov     bx, 7C00h\nReadOld01:\n\txor     ax, ax\n\tint     13h           ; Reset DISK\n\tmov     ax, 201h      ; Function 2 AH == 00000010 \/ Sectors To Read Count AL == 00000001\n\tint     13h           ; INT 13, -- Read Sectors From Drive\n\tjnb     short ReadOld02  ; error reading\n\tdec     di               ; number of retries - default 5\n\tjg      short ReadOld01  ; retry read\nReadOld02:\n\tretn\n\t; The following are the \"INT 13 Extensions Installation Check\" and\n\t; the Extended READ sectors from Hard Drive (Function 42h) routines.\n\t; **** Normal entry if Ext int13 supported after CheckINT13Ext call\nExtRead:\n\t; dl == drive number\n\tpush    ds\n\tmov     eax, [bx+8]  ; load number of sectors before partition from MBR\n\t; set fs and ds 0x3000\n\tpush    fs\n\tpop     ds\n\t; DS:SI \tsegment:offset pointer to the <a href=\"https:\/\/www.ecsdump.net\/?page_id=884\" data-internallinksmanager029f6b8e52c=\"5\" title=\"DAP\" target=\"_blank\" rel=\"noopener\">DAP<\/a>, see below\n\t; DAP == 3000:0008\n\tmov     si, 8\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 to which sectors will be transferred\n\t; 08h..0Fh    8 bytes \tabsolute number of the start of the sectors to be read (1st sector of drive has number 0)\n\tmov     ds:4, eax\n\tmov     [si+8], eax\n\txor     eax, eax      ; zero eax\n\tmov     word ptr [si], 10h     ; 00h    BYTE    10h (size of packet)\n\tmov     word ptr [si+2], 1     ; number of blocks to transfer\n\tmov     word ptr [si+4], 7C00h ; -&gt; transfer buffer\n\tmov     [si+6], ax\n\tmov     [si+0Ch], eax\n\t; DAP\"\n\t; 01  02  03  04  05  06  07  08  09  0A  0B  0C  0D  0E  0F  10\n\t; 10  00  01  00  [00 7C  00 00] [00 3F   00 00   00 00   00 00]\nReadJmp04:\n\tsub     ax, ax\n\tint     13h     ; Reset drive\n\tmov     ah, 42h  ; function number for extended read\n\tint     13h\n\tjnb     short ReadJmp05  ; Error\n\tdec     di\n\tja      short ReadJmp04  ; Retry read\nReadJmp05:\n\tpop     ds\n\tretn\nReadDrive       endp<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<div>\n<pre>; The following is an example using my current Virtual PC drive\n; src\/jfs\/utils\/libfs\/mbr.h -- from openJFS source located on Netlabs.org\n;\n; struct part {\n;     UCHAR       bootind;        \/* 0x80 means partition is bootable *\/\n;     UCHAR       starthead;      \/* head number of partition start *\/\n;     UCHAR       startsect;      \/* sector number *\/\n;     UCHAR       startcyl;       \/* cylinder number *\/\n;     UCHAR       systind;        \/* partition ID *\/\n;     UCHAR       endhead;        \/* head number of partition end *\/\n;     UCHAR       endsect;        \/* sector number *\/\n;     UCHAR       endcyl;         \/* cylinder number *\/\n;     ULONG       lsn;            \/* number of sectors before partition *\/\n;     ULONG       nsects;         \/* number of sectors in partition *\/\n; };\n;\n; struct mbr {\n;     UCHAR       code[0x1be];    \/* boot record code and data *\/\n;     struct part ptbl[4];        \/* the partition table *\/\n;     USHORT      sig;            \/* special signature *\/\n; };\n7FB8 OptiDiskSig     dd 0\n7FBC                 dw 0CC33h\n7FBE ; ***** Partition 1 *****\n7FBE _bootind        db 80h   ; bootable\n7FBF _starthead      db 1\n7FC0 _startsect      db 1\n7FC1 _startcyl       db 0\n7FC2 _systind        db 7\n7FC3 _endhead        db 3Fh\n7FC4 _endsect        db 0FFh\n7FC5 _endcyl         db 0F6h\n7FC6 _lsn            dd 3Fh\n7FCA _nsects         dd 3E7201h\n7FCE ; ***** Partition 2 *****\n7FCE Part2           db 10h dup(0)\n7FDE ; ***** Partition 3 *****\n7FDE Part3           db 10h dup(0)\n7FEE ; ***** Partition 4 *****\n7FEE Part4           db 10h dup(0)\n7FFE ; ***** Signature *****\n7FFE SigEnd          dw 0AA55h<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Loaded at 7C00h, setup stack and copy block from 7C00 to 7E00h. Push 7E20h on the stack and return near which will begin execution at 7E20h. This is the initial code loaded at 07C0:0000 and the disassembled code relocated at 07E0:0000 continues below. After relocation the entry is at 7E20, I left out the 7E00&hellip;<\/p>\n<p><a class=\"more-link\" href=\"https:\/\/www.ecsdump.net\/?page_id=257\" title=\"Continue reading &lsquo;LVM MBR Disassembled&rsquo;\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":798,"menu_order":2,"comment_status":"open","ping_status":"open","template":"page-templates\/full-width.php","meta":{"footnotes":""},"categories":[4],"tags":[20,98,101,100],"wf_page_folders":[104],"class_list":["post-257","page","type-page","status-publish","hentry","category-boot-process","tag-boot","tag-boot-sector","tag-lvm","tag-mbr"],"jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/257","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=257"}],"version-history":[{"count":0,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/257\/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=257"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=257"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=257"},{"taxonomy":"wf_page_folders","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fwf_page_folders&post=257"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}