diff options
Diffstat (limited to 'baremetal/bos')
-rw-r--r-- | baremetal/bos/3-1.hex | 51 | ||||
-rw-r--r-- | baremetal/bos/3-2.hex | 65 | ||||
-rw-r--r-- | baremetal/bos/32bit.hex | 132 | ||||
-rw-r--r-- | baremetal/bos/4.asm | 143 | ||||
-rw-r--r-- | baremetal/bos/4.xxd | 87 | ||||
-rw-r--r-- | baremetal/bos/README.md | 7 | ||||
-rw-r--r-- | baremetal/bos/bochsrc | 3 | ||||
-rw-r--r-- | baremetal/bos/print-mem-real-mode.hex | 67 |
8 files changed, 555 insertions, 0 deletions
diff --git a/baremetal/bos/3-1.hex b/baremetal/bos/3-1.hex new file mode 100644 index 00000000..bf4ef208 --- /dev/null +++ b/baremetal/bos/3-1.hex @@ -0,0 +1,51 @@ +# Bootable image. +# Boot sector must have exactly 512 bytes. +# 16-bit real mode. +# +# To convert to a disk image: +# ./bootstrap run apps/hex < baremetal/bos/3-1.hex > boot.bin +# To run: +# qemu-system-i386 boot.bin +# Or: +# bochs -f baremetal/bos/bochsrc # bochsrc loads boot.bin +# +# Expected output inside emulator: +# Booting from floppy... + +e9 fd ff + +# padding to 512 bytes + 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa + +# vim:ft=subx diff --git a/baremetal/bos/3-2.hex b/baremetal/bos/3-2.hex new file mode 100644 index 00000000..85792e26 --- /dev/null +++ b/baremetal/bos/3-2.hex @@ -0,0 +1,65 @@ +# Bootable image. +# Boot sector must have exactly 512 bytes. +# 16-bit real mode. +# +# To convert to a disk image: +# ./bootstrap run apps/hex < baremetal/bos/3-2.hex > boot.bin +# To run: +# qemu-system-i386 boot.bin +# Or: +# bochs -f baremetal/bos/bochsrc # bochsrc loads boot.bin +# +# Expected output inside emulator: +# Hello + +b4 0e # ah <- 0e (teletype output) + +b0 48 # al <- 'H' +cd 10 # int 10h +b0 65 # al <- 'e' +cd 10 # int 10h +b0 6c # al <- 'l' +cd 10 # int 10h +b0 6c # al <- 'l' +cd 10 # int 10h +b0 6f # al <- 'o' +cd 10 # int 10h + +e9 fd ff # loop forever + +# padding to 512 bytes + 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +55 aa # final 2 bytes: boot sector marker + +# vim:ft=subx diff --git a/baremetal/bos/32bit.hex b/baremetal/bos/32bit.hex new file mode 100644 index 00000000..5a85aa36 --- /dev/null +++ b/baremetal/bos/32bit.hex @@ -0,0 +1,132 @@ +# Bootable image demonstrating printing to screen in 32-bit mode. +# Must have exactly 512 bytes. +# +# To convert to a disk image: +# ./bootstrap run apps/hex < baremetal/bos/32bit.hex > boot.bin +# To run: +# qemu-system-i386 boot.bin +# Or: +# bochs -f baremetal/bos/bochsrc # bochsrc loads boot.bin +# +# Expected output inside emulator: +# H + +## 16-bit entry point + +# Boot image starts executing at address 0x7c00, +# and so occupies [0x7c00, 0x7e00). +# We don't read or write the stack before we get to 32-bit mode. + +# 00: + fa # cli # TODO: don't forget to reenable interrupts at some point + 0f 01 16 # lgdt 00/mod/indirect 010/subop 110/rm32/TODO + 80 7c # *gdt_descriptor + 0f 20 c0 # eax <- cr0 + 66 83 c8 01 # eax <- or 0x1 + 0f 22 c0 # cr0 <- eax + ea c0 7c 08 00 # far jump to initialize_32bit_mode after setting cs to the record at offset 8 in the gdt (gdt_code) + +# padding +# 15: + 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +## GDT: 3 records of 8 bytes each + +# 60: +# gdt_start: +# gdt_null: mandatory null descriptor + 00 00 00 00 00 00 00 00 +# gdt_code: (offset 8 from gdt_start) + ff ff # limit[0:16] + 00 00 00 # base[0:24] + 9a # 1/present 00/privilege 1/descriptor type = 1001b + # 1/code 0/conforming 1/readable 0/accessed = 1010b + cf # 1/granularity 1/32-bit 0/64-bit-segment 0/AVL = 1100b + # limit[16:20] = 1111b + 00 # base[24:32] +# gdt_data: (offset 16 from gdt_start) + ff ff # limit[0:16] + 00 00 00 # base[0:24] + 92 # 1/present 00/privilege 1/descriptor type = 1001b + # 0/data 0/conforming 1/readable 0/accessed = 0010b + cf # same as gdt_code + 00 # base[24:32] +# gdt_end: + +# padding +# 78: + 00 00 00 00 00 00 00 00 + +# 80: +# gdt_descriptor: + 17 00 # final index of gdt = gdt_end - gdt_start - 1 + 60 7c 00 00 # start = gdt_start + +# padding +# 85: + 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +## 32-bit code from this point (still some instructions not in SubX) + +# c0: +# initialize_32bit_mode: + 66 b8 10 00 # ax <- offset 16 from gdt_start + 8e d8 # ds <- ax + 8e d0 # ss <- ax + 8e c0 # es <- ax + 8e e0 # fs <- ax + 8e e8 # gs <- ax + e9 1d 00 00 00 # jump to 0x7cf0 + +# padding +# d3: + 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +## 'application' SubX code: print one character to top-left of screen + +# f0: +# Entry: + # *0xb8000 <- 0x0f48 + c7 # opcode + # modrm + 05 # 00/mod/indirect 000/subop/copy 101/rm32/use-disp32 + # disp32 + 00 80 0b 00 + # imm32 + 48 # 'H' + 0f # white on black + 00 00 + +e9 fb ff ff ff # loop forever + +# padding to 512 bytes + 00 +# 100: +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +55 aa # final 2 bytes: boot sector marker + +# vim:ft=subx diff --git a/baremetal/bos/4.asm b/baremetal/bos/4.asm new file mode 100644 index 00000000..71c51d97 --- /dev/null +++ b/baremetal/bos/4.asm @@ -0,0 +1,143 @@ +; A boot sector that enters 32-bit protected mode. +; +; To convert to a disk image: +; cd apps/bos +; nasm 4.asm -f bin -o boot.bin +; To run: +; qemu-system-i386 boot.bin +; Or: +; bochs # bochsrc loads boot.bin + +[org 0x7c00] + + mov bp, 0x9000 + mov sp, bp + + mov bx, MSG_REAL_MODE + call print_string + + call switch_to_pm + ; never gets here + + jmp $ + +switch_to_pm: + cli + lgdt [gdt_descriptor] + ; set LSB of CR0 + mov eax, cr0 + or eax, 0x1 + mov cr0, eax + jmp CODE_SEG:init_pm ; Far jump to a new segment containing 32-bit code. + ; This also forces the CPU to flush its cache of + ; prefetched and real-mode decoded instructions. + ; never gets here + +;; === GDT stuff +gdt_start: + +gdt_null: ; the mandatory null descriptor + dd 0x0 ; ’dd’ means define double word (i.e. 4 bytes) + dd 0x0 + +gdt_code: ; the code segment descriptor + ; base=0x0, limit=0xfffff, + ; 1st flags: (present)1 (privilege)00 (descriptor type)1 -> 1001b + ; type flags: (code)1 (conforming)0 (readable)1 (accessed )0 -> 1010b + ; 2nd flags: (granularity)1 (32-bit default)1 (64-bit seg)0 (AVL)0 -> 1100b + dw 0xffff ; Limit (bits 0-15) + dw 0x0 ; Base (bits 0-15) + db 0x0 ; Base (bits 16 -23) + db 10011010b ; 1st flags, type flags + db 11001111b ; 2nd flags, Limit (bits 16-19) + db 0x0 ; Base (bits 24 -31) + +gdt_data: ; the data segment descriptor + ; Same as code segment except for the type flags: + ; type flags: (code)0 (expand down)0 (writable)1 (accessed)0 -> 0010b + dw 0xffff ; Limit (bits 0-15) + dw 0x0 ; Base (bits 0-15) + db 0x0 ; Base (bits 16 -23) + db 10010010b ; 1st flags, type flags + db 11001111b ; 2nd flags, Limit (bits 16-19) + db 0x0 ; Base (bits 24 -31) + +gdt_end: + +gdt_descriptor: + dw gdt_end - gdt_start - 1 ; last valid byte + dd gdt_start + +; some handy constants +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start +;; === end GDT stuff + +;; some 16-bit helpers + +; print string whose address is in bx +print_string: + pusha + mov ah, 0x0e +loop: + mov al, [bx] + int 0x10 + add bx, 1 + cmp al, 0 + jne loop + popa + ret + +;; 32-bit code starts here +[bits 32] + +; Initialise registers and the stack once in PM. +init_pm: + + mov ax, DATA_SEG ; Now in PM, our old segments are meaningless, + mov ds, ax ; so we point our segment registers to the + mov ss, ax ; data selector we defined in our GDT + mov es, ax + mov fs, ax + mov gs, ax + + mov ebp, 0x90000 ; Update our stack position so it is right + mov esp, ebp ; at the top of the free space. + + ;; Protected Mode is now initialized + + mov ebx, MSG_PROT_MODE + call print_string_pm + + ; all done; hang + jmp $ + +; Define some constants +VIDEO_MEMORY equ 0xb8000 +WHITE_ON_BLACK equ 0x0f + +; prints a null -terminated string pointed to by EDX +print_string_pm: + pusha + mov edx, VIDEO_MEMORY ; Set edx to the start of vid mem. +print_string_pm_loop: + mov al, [ebx] ; Store the char at EBX in AL + mov ah, WHITE_ON_BLACK ; Store the attributes in AH + cmp al, 0 ; if (al == 0), at end of string , so + je print_string_pm_done + mov [edx], ax ; Store char and attributes at current + ; character cell. + add ebx , 1 ; Increment EBX to the next char in string. + add edx , 2 ; Move to next character cell in vid mem. + jmp print_string_pm_loop ; loop around to print the next char. +print_string_pm_done: + popa + ret ; Return from the function + +; Global variables +MSG_REAL_MODE db "Started in 16-bit Real Mode", 0 +MSG_PROT_MODE db "Successfully landed in 32-bit Protected Mode", 0 + +; Bootsector padding +times 510-($-$$) db 0 +dw 0xaa55 diff --git a/baremetal/bos/4.xxd b/baremetal/bos/4.xxd new file mode 100644 index 00000000..be677134 --- /dev/null +++ b/baremetal/bos/4.xxd @@ -0,0 +1,87 @@ +## 16-bit code + +# Entry: +00: + bd 00 90 # bp <- 0x9000 + 89 ec # sp <- bp + + bb 8f 7c # bx <- MSG_REAL_MODE + e8 38 00 # call print_string + + e8 02 00 # call switch_to_pm + eb fe # jump $ (should never get here) + +# switch_to_pm: +10: + fa # cli + 0f 01 16 3d 7c # lgdt [gdt_descriptor] + 0f 20 c0 # eax <- cr0 + 66 83 c8 01 # eax <- or 0x1 + 0f 22 c0 # cr0 <- eax +20: + ea 53 7c 08 00 # jmp CODE_SEG:init_pm + +# gdt_start: +# gdt_null: mandatory null descriptor + 00 00 00 00 00 00 00 00 +# gdt_code: + ff ff 00 +30: + 00 00 9a cf 00 +# gdt_data: + ff ff 00 00 00 92 cf 00 +# gdt_end: + +# gdt_descriptor: +3d: + 17 00 # limit + 25 7c 00 00 # start + +# print_string: +43: + 60 # pusha + b4 0e # ah <- 0x0e +# loop: + 8a 07 # al <- *bx + cd 10 # int 10h + 83 c3 01 # add bx, 1 + 3c 00 # cmp al, 0 + 75 f5 # jne loop + 61 # popa + c3 # ret + +## 32-bit code + +# init_pm: +53: + 66 b8 10 00 # ax <- DATA_SEG + 8e d8 # ds <- ax + 8e d0 # ss <- ax + 8e c0 # es <- ax + 8e e0 # fs <- ax + 8e e8 # gs <- ax +61: + bd 00 00 09 00 # ebp <- 0x90000 + 89 ec # esp <- ebp + bb ab 7c 00 00 # ebx <- MSG_PROT_MODE + e8 02 00 00 00 # call print_string_pm + eb fe # hang + +# print_string_pm: +74: + 60 # pusha + ba 00 80 0b 00 8a 03 b4 0f 3c 00 +80: + 74 0b 66 89 02 83 c3 01 83 c2 02 eb ed 61 c3 53 +90: + 74 61 72 74 65 64 20 69 6e 20 31 36 2d 62 69 74 +a0: + 20 52 65 61 6c 20 4d 6f 64 65 00 53 75 63 63 65 +b0: + 73 73 66 75 6c 6c 79 20 6c 61 6e 64 65 64 20 69 +c0: + 6e 20 33 32 2d 62 69 74 20 50 72 6f 74 65 63 74 +d0: + 65 64 20 4d 6f 64 65 + +# vim:ft=conf diff --git a/baremetal/bos/README.md b/baremetal/bos/README.md new file mode 100644 index 00000000..989ebf44 --- /dev/null +++ b/baremetal/bos/README.md @@ -0,0 +1,7 @@ +Exercises while reading the incomplete "Writing a simple operating system from +scratch" by Nick Blundell. + https://www.cs.bham.ac.uk/~exr/lectures/opsys/10\_11/lectures/os-dev.pdf + +The name of this directory is a reference to "Bootstrapping a simple compiler +from nothing" by Edmund Grimley-Evans. + https://github.com/certik/bcompiler diff --git a/baremetal/bos/bochsrc b/baremetal/bos/bochsrc new file mode 100644 index 00000000..de225b4c --- /dev/null +++ b/baremetal/bos/bochsrc @@ -0,0 +1,3 @@ +ata0-master: type=disk, path="boot.bin", mode=flat, cylinders=1, heads=1, spt=1 +boot: disk +log: - diff --git a/baremetal/bos/print-mem-real-mode.hex b/baremetal/bos/print-mem-real-mode.hex new file mode 100644 index 00000000..3610308c --- /dev/null +++ b/baremetal/bos/print-mem-real-mode.hex @@ -0,0 +1,67 @@ +# Experiment: write to video RAM from 16-bit real mode. And it works. +# +# To convert to a disk image: +# ./bootstrap run apps/hex < baremetal/bos/print-mem-real-mode.hex > boot.bin +# To run: +# qemu-system-i386 boot.bin +# Or: +# bochs # reads bochsrc, which loads boot.bin + +# - figure 4.1 of https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf in protected mode +# edx <- 0xb8000 +# al <- 'H' +# ah <- 0x0f # white on black +# *edx <- ax + +# - translating to real mode +# bx <- 0xb800 +bb 00 b8 +# ds <- bx +8e db # 11b/mod 011b/reg/ds 011b/rm/bx +# al <- 'H' +b0 48 +# ah <- 0x0f # white on black +b4 0f +# bx <- 0 +bb 00 00 +# *ds:bx <- ax +89 07 # 00b/mod/indirect 000b/reg/ax 111b/rm/bx + +e9 fd ff # loop forever + +# padding to 512 bytes + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +55 aa # final 2 bytes: boot sector marker + +# vim:ft=subx |