{"id":121,"date":"2015-07-19T07:34:11","date_gmt":"2015-07-19T11:34:11","guid":{"rendered":"http:\/\/72.167.111.237\/wpecsdump\/?page_id=121"},"modified":"2020-12-08T17:35:40","modified_gmt":"2020-12-08T22:35:40","slug":"boot-sector-example-by-jeff-weeks","status":"publish","type":"page","link":"https:\/\/www.ecsdump.net\/?page_id=121","title":{"rendered":"Boot Sector Example \u2013 by Jeff Weeks"},"content":{"rendered":"<p><em>Note: From OSRC, pulled from <a href=\"https:\/\/web.archive.org\/web\/20130618062859\/http:\/\/www.nondot.org\/sabre\/os\/files\/Booting\/PolyOS.html\" target=\"_blank\" rel=\"noopener noreferrer\">Wayback Machine<\/a><\/em><br \/>\n<u><span style=\"font-size: medium;\">W<\/span>RITING <span style=\"font-size: medium;\">A<\/span> <span style=\"font-size: medium;\">B<\/span>OOTSECTOR <\/u><br \/>\n(c)1997 Jeff Weeks and Code X software<br \/>\nWritting your own boot sector is probably actually easier then you think. All you really need to know is how the Intel processor boots up. A valid boot sector has the code 0xAA55 at an offset of 510, and is located in the very first sector of the disk. Therefore, the BIOS simply checks drive 0 (A:) for this code. If not found, it then checks drive 128 (C:). If a valid boot sector is found, it is loaded into memory at location 0:07C00h.<br \/>\nSo, all you have to do is write a boot sector, assemble it into a plain binary file (their is no format or header to a boot sector), and write it to the first sector of your disk. The best way to do that would be to either use nasm (The netwide assembler can produce plain binary files) or assemble into a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Disk_operating_system\" data-internallinksmanager029f6b8e52c=\"2\" title=\"DOS\" target=\"_blank\" rel=\"noopener\">DOS<\/a> .EXE and remove the first 512 bytes. You can also write your own program to write the bootsector to sector 1 of the disk using BIOS INT 13h AH=02h.<br \/>\nPretty simple eh? Well, in case you&#8217;re still a little confused, here&#8217;s a little bootsector from PolyOS that simply switches to protected mode, after checking that you have a 386+ computer. Actually, it even loads in the PolyFS superblock and checks if it&#8217;s valid, but that&#8217;s about it. Soon it&#8217;ll load in the kernel and jump to it. The bootesctor was written with Nasm.<br \/>\n&nbsp;<\/p>\n<pre lang=\"asm\">; ------------------------------------------------------------------------\n; PolyOS boot loader code            (c)1997 Jeff Weeks of Code X Software\n; ------------------------------------------------------------------------\n; This little bit of assembly is the boot loader for my operating system.\n; ------------------------------------------------------------------------\n[BITS 16]       ; the bios starts out in 16-bit real mode\n[ORG 0]\n; ------------------------------------------------------------------------\n; SECTOR ONE: THE BOOT LOADER\n; ------------------------------------------------------------------------\n; This sector detects your processor.  If a 386 is found, it loads the\n; kernel from the disk and executes it (atleast it will in the future :).\n; ------------------------------------------------------------------------\njmp start       ; skip over our data and functions\n; -------------------------------------\n; Data used in the boot-loading process\n; ------------------------------------------------------------------------\n        bootdrv         db 0\n        bootmsg         db 'Booting PolyOS (c)1997 Cipher of Code X',13,10,0\n        loadmsg         db 'Loading kernel',13,10,0\n        jumpmsg         db 'Jumping to kernel',13,10,0\n        rebootmsg       db 'Press any key to reboot',13,10,0\n        ; these are used in the processor identification\n        processormsg    db 'Checking for 386+ processor: ',0\n        need386         db 'Sorry... 386+ required!',13,10,0\n        found386        db 'Excellent!',13,10,0\n        ; these are used when entering protected mode\n        a20msg          db 'Setting A20 address line',13,10,0\n        pmodemsg        db 'Setting CR0 -&gt; Entering PMode',13,10,0\n        ; Here's the locations of my IDT and GDT.  Remember, Intel's are\n        ; little endian processors, therefore, these are in reversed order.\n        ; Also note that lidt and lgdt accept a 32-bit address and 16-bit\n        ; limit, therefore, these are 48-bit variables.\n        pIDT            dw 7FFh         ; limit of 256 IDT slots\n                        dd 0000h        ; starting at 0000\n        pGDT            dw 17FFh        ; limit of 768 GDT slots\n                        dd 0800h        ; starting at 0800h (after IDT)\n; ------------------------------------------\n; Functions used in the boot-loading process\n; ------------------------------------------------------------------------\n        detect_cpu:\n                mov si, processormsg    ; tell the user what we're doing\n                call message\n                ; test if 8088\/8086 is present (flag bits 12-15 will be set)\n                pushf                   ; save the flags original value\n                xor ah,ah               ; ah = 0\n                push ax                 ; copy ax into the flags\n                popf                    ; with bits 12-15 clear\n                pushf                   ; Read flags back into ax\n                pop ax\n                and ah,0f0h             ; check if bits 12-15 are set\n                cmp ah,0f0h\n                je no386                ; no 386 detected (8088\/8086 present)\n                ; check for a 286 (bits 12-15 are clear)\n                mov ah,0f0h             ; set bits 12-15\n                push ax                 ; copy ax onto the flags\n                popf\n                pushf                   ; copy the flags into ax\n                pop ax\n                and ah,0f0h             ; check if bits 12-15 are clear\n                jz no386                ; no 386 detected (80286 present)\n                popf                    ; pop the original flags back\n                mov si, found386\n                call message\n                ret                     ; no 8088\/8086 or 286, so ateast 386\n         no386:\n                mov si,need386          ; tell the user the problem\n                call message\n                jmp reboot              ; and reboot when key pressed\n;       ------------------------------------------------------------------\n        message:                        ; Dump ds:si to screen.\n                lodsb                   ; load byte at ds:si into al\n                or al,al                ; test if character is 0 (end)\n                jz done\n                mov ah,0eh              ; put character\n                mov bx,0007             ; attribute\n                int 0x10                ; call BIOS\n                jmp message\n        done:\n                ret\n;       ------------------------------------------------------------------\n        getkey:\n                mov ah, 0               ; wait for key\n                int 016h\n                ret\n;       ------------------------------------------------------------------\n        reboot:\n                mov si, rebootmsg       ; be polite, and say we're rebooting\n                call message\n                call getkey             ; and even wait for a key :)\n                db 0EAh                 ; machine language to jump to FFFF:0000 (reboot)\n                dw 0000h\n                dw 0FFFFh\n                ; no ret required; we're rebooting! (Hey, I just saved a byte :)\n; -------------------------------------------\n; The actual code of our boot loading process\n; ------------------------------------------------------------------------\nstart:\n        mov ax,0x7c0    ; BIOS puts us at 0:07C00h, so set DS accordinly\n        mov ds,ax       ; Therefore, we don't have to add 07C00h to all our data\n        mov [bootdrv], dl ; quickly save what drive we booted from\n        cli             ; clear interrupts while we setup a stack\n        mov ax,0x9000   ; this seems to be the typical place for a stack\n        mov ss,ax\n        mov sp,0xffff   ; let's use the whole segment.  Why not?  We can :)\n        sti             ; put our interrupts back on\n        ; Interestingly enough, apparently the processor will disable\n        ; interupts itself when you directly access the stack segment!\n        ; Atleast it does in protected mode, I'm not sure about real mode.\n        mov si,bootmsg  ; display our startup message\n        call message\n        call detect_cpu ; check if we've got a 386\n.386    ; use 386 instructions from now on (I don't want to manually include\n        ; operand-size(66h) or address-size(67h) prefixes... it's annoying :)\n        mov si,loadmsg  ; tell the user we're loading the kernel\n        call message\n        call getkey\nread_me:\n        ; first, reset the disk controller\n        xor ax, ax\n        int 0x13\n        jc reboot       ; reboot on error\n        ; then load in the PolyFS superblock\n        mov ax,0x09000          ; superblock goes to 9000:0000 (above stack)\n        mov es,ax\n        xor bx,bx\n        ; I could condense a few of these high\/low 8-bit movs into one 16-bit\n        ; mov, but, for simplicity, I'll leave it as is, unless necessary.\n        mov ax,0x0202           ; load one block (two sectors)\n        mov ch,0                ; cylinder = 0\n        mov cl,3                ; sector = 2 (starts at sector 1 not 0)\n        mov dh,0                ; head = 0 = side one\n        mov dl,[bootdrv]        ; disk = what we booted from\n        int 0x13                ; read it\n        jc read_me              ; if there's an error then we'll try again.\n                                ; Often there is not error but requires a few\n                                ; tries.  Ofcourse, this may end up as an\n                                ; infinite loop... but only on a bad disk...\n        ; Check if we have a valid super block (BTW: ES still equals 0x9000)\n        mov di, 0               ; offset of PolyFS magic signature\n        mov si, polymagic       ; offset of PolyFS magic to check for (in ds)\n        cmpsw                   ; compare ES:[DI] with DS:[SI]\n        jnz reboot              ; reboot on error (otherwise, we've got a PolyFS)\n\t; Ideally, we'd load the kernel right here\n        mov si, a20msg          ; tell the user we're setting the A20 line\n        call message\n        ; set A20 line\n        cli                     ; no more interuptions! :)\n        xor cx, cx\nclear_buf:\n        in al, 64h              ; get input from keyboard status port\n        test al, 02h            ; test the buffer full flag\n        loopnz clear_buf        ; loop until buffer is empty\n        mov al, 0D1h            ; keyboard: write to output port\n        out 64h, al             ; output command to keyboard\nclear_buf2:\n        in al, 64h              ; wait 'till buffer is empty again\n        test al, 02h\n        loopnz clear_buf2\n        mov al, 0dfh            ; keyboard: set A20\n        out 60h, al             ; send it to the keyboard controller\n        mov cx, 14h\nwait_kbc:                       ; this is approx. a 25uS delay to wait\n        out 0edh, ax            ; for the kb controler to execute our\n        loop wait_kbc           ; command.\n        ; the A20 line is on now.  Let's load in our ITD and GDT tables...\n        ; Ideally, there will actually be data in their locations (by loading\n        ; the kernel)\n        lidt [pIDT]\n        lgdt [pGDT]\n        ; now let's enter pmode...\n        mov si, pmodemsg\n        call message\n        call getkey\n        mov eax, cr0            ; load the control register in\n        or  al, 1               ; set bit 1: pmode bit\n        mov cr0, eax            ; copy it back to the control register\n        jmp $+2                 ; and clear the prefetch queue\n        nop\n        nop\n        ; jump to the kernel that we've loaded in...\n        ; For now, we'll actually just reboot (this really doesn't\n        ; work in protected mode, but it does reboot :)\n        db 0xEA\n        dw 0x0000\n        dw 0xFFFF\n        ; The boot sector is supposed to have to have 0xAA55 at the end of\n        ; the sector (the word at 510 bytes) to be loaded by the BIOS...\n        times 510-($-$) db 0\n        dw 0xAA55<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Note: From OSRC, pulled from Wayback Machine WRITING A BOOTSECTOR (c)1997 Jeff Weeks and Code X software Writting your own boot sector is probably actually easier then you think. All you really need to know is how the Intel processor boots up. A valid boot sector has the code 0xAA55 at an offset of 510,&hellip;<\/p>\n<p><a class=\"more-link\" href=\"https:\/\/www.ecsdump.net\/?page_id=121\" title=\"Continue reading &lsquo;Boot Sector Example \u2013 by Jeff Weeks&rsquo;\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"open","template":"page-templates\/full-width.php","meta":{"footnotes":""},"categories":[4],"tags":[20,30],"wf_page_folders":[85],"class_list":["post-121","page","type-page","status-publish","hentry","category-boot-process","tag-boot","tag-reference"],"jetpack_sharing_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/121","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=121"}],"version-history":[{"count":0,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=\/wp\/v2\/pages\/121\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=121"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=121"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=121"},{"taxonomy":"wf_page_folders","embeddable":true,"href":"https:\/\/www.ecsdump.net\/index.php?rest_route=%2Fwp%2Fv2%2Fwf_page_folders&post=121"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}