{"id":659,"date":"2020-12-05T10:49:59","date_gmt":"2020-12-05T10:49:59","guid":{"rendered":"https:\/\/www.ecsdump.net\/?page_id=659"},"modified":"2020-12-08T11:56:50","modified_gmt":"2020-12-08T11:56:50","slug":"boot-sector","status":"publish","type":"page","link":"https:\/\/www.ecsdump.net\/?page_id=659","title":{"rendered":"Boot Sector"},"content":{"rendered":"<p>The boot sector is compiled and inserted on to the test hard drive image. My manual <a href=\"https:\/\/en.wikipedia.org\/wiki\/BIOS_parameter_block\" data-internallinksmanager029f6b8e52c=\"4\" title=\"BPB\" target=\"_blank\" rel=\"noopener\">BPB<\/a> compiled with UASM and use dd to manually install on my 50 Meg <a href=\"https:\/\/en.wikipedia.org\/wiki\/Disk_operating_system\" data-internallinksmanager029f6b8e52c=\"2\" title=\"DOS\" target=\"_blank\" rel=\"noopener\">DOS<\/a> vdi. I cannot remember why I used UASM instead of wasm or jwasm, but maybe it will come to me.<\/p>\n<h2>Overall Purpose<\/h2>\n<p>Only does LBA reads &#8211; int 13 0x41 check error if no extensions. Assumes a modern system has more than 1 meg RAM so no TOM check. The basic function this BPB:<\/p>\n<ol>\n<li>Loads watload.bin to 0xC000<\/li>\n<li>Overlay BIOS parameter block (BPB) data to watload.bin<\/li>\n<li>Far jump to watload.bin<\/li>\n<\/ol>\n<p>This is the big start and the following is a memory map I threw together to help track of what memory areas I was using. The example is a simple old 32bit system boot which starts in real mode (16bit). The following represents the boot block found by the system as the machine initializes and loaded to 0x0000:0x7C00. Once the BIOS initializes, it jumps to 0x0000:0x7C00 and it is all you at that point, no safety nets.&nbsp;<\/p>\n\n\n<pre lang=\"language-asm\">;\t --------  \n;\t|        | \n;\t|watload | at 0xC000 (0x800 bytes)\n;\t+--------+\n;\t|        | \n;\t| Buffer | Use start 0x7E00 for Root Dir and FAT load buffer\n;\t|--------| 0000:7E00  (0:BP+200)\n;\t|BOOT SEC| contains BPB\n;\t|ORIGIN  |\n;\t|--------| 0000:7C00  (0:BP)\n;\t|VARS    | only known is 1st data sector (start of cluster 2)\n;\t|--------| 0000:7BFC  (DS:[BP-4])\n;\t|STACK   | minimal 256 bytes (1\/2 sector)\n;\t|- - - - |\n;\t|KERNEL  | kernel loaded here (max 58 sectors, 29KB)\n;\t|LOADED  | also used as FAT buffer\n;\t|--------| 0070:0000 (0:0700)\n;\t|KERNEL  | \n;\t|LOADED  | \n;\t|--------| 0000:0600 \n;\t|DOS DA  | DOS Data Area,\n;\t|        | Cluster list temp from FAT read\n;\t|********| 0000:0500\n;\t|BDA     | BIOS Data Area\n;\t+--------+ 0000:0400\n;\t|IVT     | Interrupt Vector Table\n;\t+--------+ 0000:0000\n<\/pre>\n\n\n<h2>It&#8217;s All You<\/h2>\n<p>This is the most rewarding thing about learning the low level stuff, it is all you from this point. When it works, there is nothing like. When it doesn&#8217;t work, there is nothing like it. In the next snippet, I set up some address for use and add\u00a0 <em>daptable.inc<\/em>. Note the nop to keep the short jmp.<\/p>\n\n\n<pre lang=\"language-asm\">;\n.8086 ; enable assembler warnings to limit instruction set\n\ninclude daptable.inc\n\nBASE\t    equ\t0x7C00      ; boot sector originally at 0x0:BASE\nBUFFER_SEG  equ 0x07E0\nBUFFER_OFF  equ 0x0000      ; buffer at 0x7E00 for Root and FAT load\nBIOS_SEG    equ 0x0C00      ; watload.bin load at 0xC000\nCLUSTERLIST equ 0x0500      ; location to store bios cluster list\n\n;-----------------------------------------------------------------------\n; Entry point after MBR hand off. Stock MBR is located at 0000:0x0600\n\n_TEXT segment use16 'code'\n            org     BASE\n\nBS_jmpBoot:     \n    jmp     short start\n    nop\n\n<\/pre>\n\n\n<h2>BIOS parameter block (BPB)<\/h2>\n<p>So, this is the BPB and some form of BPB, for whatever filesystem in use, will be written when the media is formatted. In my case, I made my test drive image, FAT, and pulled the BPB for use in my boot sector.&nbsp;<\/p>\n\n\n<pre lang=\"language-asm\">BPB_Start:\nBS_OEMName      db 'IBM  7.0'   ; OEM label\n\nBPB_BytsPerSec \tdw 0x200        ; Number of bytes per sector (512) Must be one of 512, 1024, 2048, 4096.\nBPB_SecPerClus \tdb 0x4          ; Number of sectors per cluster Must be one of 1, 2, 4, 8, 16, 32, 64, 128.\nBPB_RsvdSecCnt \tdw 0x1          ; reserved sectors, in 12\/16 usually 1 for BPB, FAT32 uses 32\nBPB_NumFATs    \tdb 0x2          ; number of FATs, \nBPB_RootEntCnt \tdw 0x200        ; root directory entries, 0 for FAT32. 512 is recommended for FAT16.\nBPB_TotSec16   \tdw 0x0          ; 16-bit total count of sectors on the volume, if 0 see BPB_TotSec32\nBPB_Media       db 0xF8         ; is no longer usually used, F8 HD FA Ram Disk\nBPB_FATSz16    \tdw 0x64         ; sectors per 1 FAT copy\nBPB_SecPerTrk  \tdw 0x3F         ; sectors per track\nBPB_NumHeads    dw 0x10         ; number of heads\nBPB_HiddSec    \tdd 0x3F         ; hidden sectors\nBPB_TotSec32   \tdd 0x18D71      ; big total sectors  BPB_TotSec32 * BPB_BytsPerSec = HD size\n\nBS_DrvNum      \tdb 0x80         ; boot unit\nBS_Reserved1   \tdb 0            ; Reserved (used by Windows NT). FAT always 0\nBS_BootSig     \tdb 0x29         ; 0x29 indicates next 3 fields in the boot sector present\nBS_VolID       \tdd 0x30E1671C   ; volume serial number\nBS_VolLab      \tdb 'PCDOS_DEV  '; volume label\nBS_FilSysType  \tdb 'FAT16   '   ; filesystem id\n\nfat_start       dd  ?           ; first FAT sector\ndata_start      dd  ?           ; first Data sector\nbios_cluster    dw  ?           ; bios cluster from root dir \n<\/pre>\n\n\n<h2>Disk Address Packet (DAP)<\/h2>\n<p>The <a href=\"https:\/\/www.ecsdump.net\/?page_id=884\" data-internallinksmanager029f6b8e52c=\"5\" title=\"DAP\" target=\"_blank\" rel=\"noopener\">DAP<\/a> is used for LBA reads and was included early. This link: <a href=\"https:\/\/www.ecsdump.net\/?page_id=884\" target=\"_blank\" rel=\"noopener noreferrer\"><em>daptable.inc<\/em><\/a> shows the DAP with comments.<\/p>\n\n\n<pre lang=\"language-asm\">\n; DAP : Disk Address Packet \nDAP DAP_TABLE <0x10,0x0,0x0,0x7E00,0x0,0x0,0x0>\n<\/pre>\n\n\n<h2>BPB Code<\/h2>\n<p>This is where the previous short jump leads us to, the start of the code.<\/p>\n<pre lang=\"language\">\n ********************************************************************\n; * Start of BPB code\n; ********************************************************************\nstart:\n    cli             \t\t\n    cld             \t\t\n    mov     BS_DrvNum, dl   ; save BIOS drive number\n    xor     ax, ax  \t\t; segment registers 0x0000\n    mov     ds, ax  \t\t\n    mov     es, ax\n    mov     ss, ax\n    mov     bp, BASE        ; setup stack\n    mov     sp, BASE\n    sti             \t\t\n\n; Volume Structure:\n;      |       |       |            |\n;  BPB |  FAT  |  FAT  |  Root Dir  |  Data\n;      |       | Copy  |            |\n;      |       |       |            |\n;   fat_start       dir_start   data_start\n\n    ; fat_start = BPB_HiddSec + BPB_RsvdSecCnt\n    mov    si, word ptr BPB_HiddSec\n    mov    di, word ptr BPB_HiddSec+2\n    add    si, word ptr BPB_RsvdSecCnt\n    adc    word ptr fat_start+2, di  ; DI:SI = first FAT sector\n    mov    word ptr fat_start, si\n\n    ; dir_start = (BPB_NumFATs * BPB_FATSz16) + fat_start\n    mov    al, BPB_NumFATs\n    cbw\n    mul    BPB_FATSz16       \t   ; DX:AX = total number of FAT sectors\n    add    si, ax\n    adc    di, dx                  ; DI:SI = first root directory sector\n    mov\t   word ptr DAP.DAP_sector_low, si\t\t\n    mov\t   word ptr DAP.DAP_sector_low+2, di  ; root dir start in DAP will be \n                                              ; first read in\n                                           \n    ; RootDirSectors = (BPB_RootEntCnt * 32) \/ BPB_BytsPerSec;\n    mov    ax, 32\n    xor    dx, dx\n    mul    word ptr BPB_RootEntCnt\n    div    word ptr BPB_BytsPerSec        ; Divide (dx:ax,sectsize) to (ax,dx)\n    mov    DAP.DAP_num_sectors, ax        ; number of root dir sectors to DAP\n                                               \n    ; where the data starts\n    add    si, ax\n    mov    word ptr data_start, si\n    adc    word ptr data_start+2, di      ; DI:SI = first data sector\n\n    ; First, read the root directory into buffer.\n    ; IBM\/MS INT 13 Extensions - INSTALLATION CHECK\n    ; will not work without LBA extensions\n    mov    ah,041h             \n    mov    bx,055aah           \n    mov    dl, [BS_DrvNum]     ; BIOS drive, 0=A:, 80=C:\n    int    0x13\n    jnc    root_read\n    mov    ax, 0x0E31\n    jmp    print_error         ; Error 1 - No bios extensions\n    \n    ; yep, damn - int 13  0x42 is supported, read in full root dir at\n    ; 0x7E00 - big read\nroot_read:\n    call   readdrive           ; read in root directory\n    jnc\t   get_biosname        \n    mov    ax, 0x0E32\n    jmp    print_error         ; Error 2 - Root directory read\n    \n    ; read through root dir directory for watload.bin \nget_biosname:\n    lea    si, filename        ;Starting address of first buffer\n    lea    di, buffer\t       ;Starting address of first buffer\n    push   si\n    push   di\n    mov\t   ax, BPB_RootEntCnt  ;Count FAT 16 directory entries max\n    \nnext_dir:\n    mov\t   cx, 0x0B            ;Scanning 11 bytes (CX is used by REPE)\n    repe   cmpsb               ;   ...and compare it.\n    je     bios_found \n    pop\t   di\n    add\t   di, 0x20\n    pop\t   si\n    push   si\n    push   di\n    cmp    byte ptr [es:di], 0x00\n    jz\t   no_bios\t           ; ax counts max dir entries, but if first \n    dec\t   ax                  ; char di is zero, no more dir entries\n    jne\t   next_dir            ; so bail early\n\n    ; get here if entry not found 0x00, first free entry or for some \n    ; reason you read through all entries not found or 0xE5 and \n    ; ax counts down to zero\nno_bios:\n    mov    ax, 0x0E33\n    jmp    print_error         ; Error 3 - watload.bin\nbios_found:\n    pop    di                  ; offset of found dir entry\n    pop    si                  ; empty stack\n\n    ; watload directory entry found, pull cluster, store in data\n    mov    ax, [di+0x1A]       ; first cluster\n    mov    [bios_cluster], ax\n\n    ; reuse DAP structure - setup DAP for FAT read. Read in full FAT\n    ; at 0x7E00\n    lea    bx, buffer\t\t\t\n    mov    ax, [BPB_FATSz16]\n    mov\t   DAP.DAP_num_sectors, ax    \n    mov    ax, word ptr [fat_start]\n    mov    dx, word ptr [fat_start+2] \n    mov\t   word ptr DAP.DAP_sector_low, ax\t\t\n    mov\t   word ptr DAP.DAP_sector_low+2, dx \n    call   readdrive           ; read FAT into memory at 0x7E00\n    jnc\t   read_fat\n    mov    ax, 0x0E35\n    jmp    print_error          ; Error 5 - FAT read error\n\nread_fat:\n    ; set up ds:di to the FAT buffer\n    mov    si, BUFFER_OFF\n    mov    ax, BUFFER_SEG\n    mov    ds, ax\n    mov    ax, [ds:si]\n    sub    ax, 0xFFF8\n    je     good_fat_table      ; first word should be 0xFFF8 or \n    mov    ax, 0x0E36\n    jmp    print_error         ; Error 6 - FAT table bad\n\n; At this point, the entire FAT is loaded at 0x7E00 and ds:si are set\n; to that seg:off. Assume es - 0, set es:di 0000:0500\n\ngood_fat_table:\n    lea    di, [CLUSTERLIST]\n    mov    ax, bios_cluster    ; cluster number from root dir\nnext_clust:\n    stosw                       ; store cluster number, inc next after store\n    mov    si, ax\n    add    si, si              ; cluster * 2\n    mov    ax, [ds:si]\n   \n    ; In some docs the end-of-clusterchain marker is listed as FFF8, but\n    ; in others FFFF (FAT16). From what I have seen FFFF is the correct \n    ; marker and FFF8 is only at cluster 1 position.\n    cmp    ax, 0xFFFF\n    jne    next_clust\n    xor    ax, ax              ; mark end of temp cluster list 0x0000\n    stosw \n    \n    ; set ds back to 0x0000 so my next int 13 0x42 reads the DAP at the\n    ; correct address\n    mov    ds, ax   \n    \n    ; ************************************************************** \n    ; ****      Note: buffer at 0x7E00 no longer needed         **** \n    ; ************************************************************** \n    \n    ; The issue is that the stock IBMBIOS loads at 0x0700 and a full \n    ; load will over write \n    mov    DAP.DAP_buffer_off, ax ; load to DAP off -- 0x0000\n    mov    ax, BIOS_SEG           ; load segment\n    mov    DAP.DAP_buffer_seg, ax ; load to DAP seg -- 0x0D00\n    mov    al, [BPB_SecPerClus]   ; each read will be size of cluster\n    cbw\n    mov    DAP.DAP_num_sectors, ax ; load in DAP\n    \n    ; LBA_sector = ((cluster_number - 2) * BPB_SecPerClus) + data_start\n    ; Start read at LBA_sector for BPB_SecPerClus\n    ; then read next cluster number and repeat until loaded    \n    lea    di, [CLUSTERLIST]\n\n    mov    ax, word ptr [data_start]    ; low word data_start\n    mov\t   word ptr DAP.DAP_sector_low, ax\t\t\n    mov    ax, word ptr [data_start+2]  ; high word data_start\n    mov\t   word ptr DAP.DAP_sector_low+2, ax  \n    xor    dx, dx\n    mov    ax, [es:di]\n    sub    ax, 0x0002             ; subtract 2, comp for FAT position\n    mul    [BPB_SecPerClus]       ; dx:ax\n    add    word ptr [DAP.DAP_sector_low], ax\n    add    word ptr [DAP.DAP_sector_low+2], dx\n    call   readdrive    \n\n    mov    cx, word ptr [fat_start]\n    mov    dx, word ptr [fat_start+2]    \n    mov    si, word ptr data_start\n    mov    di, word ptr data_start+2 \n\n    ; far jump to the start of watload.bin\t\n    jmp far ptr loader_start\n\n; Print string pointed to by DS:SI using\n; BIOS TTY output via int 10h\/AH=0eh\nprint_error:\n    int    0x10\n    jmp $\n\nreaddrive:\n    mov    ah, 0x42\n    mov    dl, BS_DrvNum\n    lea\t   si, DAP\n    int    0x13                \n\tret\n\nfilename     db  \"WATLOAD BIN\"\t\t\t\n\n; Fill free space between code\/data and signature with zero\n             db\t ((0x200 - 2) - ($ - BS_jmpBoot)) dup(0)\n\n; True, the MBR checks at 0x7DFE after BPB loaded for signature before\n; jumping to start. -MKG\nsignature    dw  0xAA55\n\n; This will be 0x7E00 - where FAT16 RootDir will load and reuse for\n; FAT read - for FAT I set ds:di == 0x7E00 \nbuffer:\t\t\t\n\n_TEXT ends\n\nloader segment use16 'code' at 0x0000\n            org     0xC000\n\n    loader_start label near \n\nloader ends\n\n<\/pre>","protected":false},"excerpt":{"rendered":"<p>The boot sector is compiled and inserted on to the test hard drive image. My manual BPB compiled with UASM and use dd to manually install on my 50 Meg DOS vdi. I cannot remember why I used UASM instead of wasm or jwasm, but maybe it will come to me. Overall Purpose Only does&hellip;<\/p>\n<p><a class=\"more-link\" href=\"https:\/\/www.ecsdump.net\/?page_id=659\" title=\"Continue reading &lsquo;Boot Sector&rsquo;\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":622,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"page-templates\/full-width.php","meta":{"footnotes":""},"categories":[4,56],"tags":[55,20,53],"wf_page_folders":[69],"class_list":["post-659","page","type-page","status-publish","hentry","category-boot-process","category-watdos","tag-asm","tag-boot","tag-watdos"],"jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/659","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=659"}],"version-history":[{"count":0,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/659\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/622"}],"wp:attachment":[{"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=659"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=659"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=659"},{"taxonomy":"wf_page_folders","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fwf_page_folders&post=659"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}