Skip to content

Commit ce91fdf

Browse files
committed
Add boot capability in MBR
partition() is now able to create an active and bootable primary MBR partition with universal boot code (LBA/CHS).
1 parent de35961 commit ce91fdf

5 files changed

Lines changed: 113 additions & 3 deletions

File tree

FATtools/partutils.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ class MBR(object):
148148
0x1FE: ('wBootSignature', '<H') # 55 AA
149149
} # Size = 0x200 (512 byte)
150150

151+
# my universal boot code
152+
boot_code = b'\x31\xC9\xFA\x8E\xD1\xBC\x00\x7C\x8E\xD9\x8E\xC1\xFB\x89\xE3\x89\xDE\xBF\x00\x06\xB9\x00\x01\xFC\xF3\xA5\xEA\x1F\x06\x00\x00\xBE\xBE\x07\x80\x3C\x80\x74\x1C\x83\xC6\x10\x81\xFE\xFE\x07\x7C\xF2\xBE\x86\x06\xAC\x3C\x00\x74\x08\x31\xDB\xB4\x0E\xCD\x10\xEB\xF3\xF4\xEB\xFD\xB4\x42\x87\xFE\xBE\x5C\x06\x8B\x4D\x08\x89\x4C\x08\x8B\x4D\x0A\x89\x4C\x0C\xCD\x13\x87\xFE\x73\x1D\x10\x00\x01\x00\x00\x7C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xB8\x01\x02\x8B\x4C\x02\x8A\x74\x01\xCD\x13\x72\xB7\x81\x3E\xFE\x07\x55\xAA\x75\xAF\xEA\x00\x7C\x00\x00\x4E\x6F\x74\x68\x69\x6E\x67\x20\x74\x6F\x20\x62\x6F\x6F\x74\x2E\x00'
153+
151154
def __init__ (self, s=None, offset=0, stream=None, disksize=0, sector=512):
152155
self._sector = sector # physical sector size (512 or 4096)
153156
self._i = 0
@@ -157,6 +160,7 @@ def __init__ (self, s=None, offset=0, stream=None, disksize=0, sector=512):
157160
self.heads_per_cyl = 0 # Heads Per Cylinder (max 255)
158161
self.sectors_per_cyl = 0 # Sectors Per Cylinder (max 63)
159162
self.is_lba = 0
163+
self.is_bootable = False # determine if add boot code and set bStatus
160164
self._kv = self.layout.copy()
161165
self._vk = {} # { name: offset}
162166
self.partitions = []
@@ -175,6 +179,8 @@ def __init__ (self, s=None, offset=0, stream=None, disksize=0, sector=512):
175179
def pack(self, sector=512):
176180
"Update internal buffer"
177181
self.wBootSignature = 0xAA55 # set valid record signature
182+
if self.is_bootable:
183+
self._buf[0:len(self.boot_code)] = self.boot_code
178184
for k, v in list(self._kv.items()):
179185
self._buf[k:k+struct.calcsize(v[1])] = struct.pack(v[1], getattr(self, v[0]))
180186
for i in self.partitions:
@@ -214,7 +220,6 @@ def setpart(self, index, start, size):
214220
pa.sLastSectorCHS = chs2raw((1023, 254, 63))
215221
else:
216222
pa.sLastSectorCHS = chs2raw(pa.sLastSectorCHS)
217-
#~ if index==0: pa.bStatus = 0x80 # always set as active
218223
pa.bType = get_min_mbrtype(size) # effective type must be set after formatting
219224
if index > 0:
220225
pa.bType = 5 # Extended CHS
@@ -257,13 +262,14 @@ def mkpart(self, offset, size):
257262
return dwFirstSectorLBA, dwTotalSectors, sFirstSectorCHS, sLastSectorCHS
258263

259264
def partition(disk, fmt='gpt', options={}):
260-
"Makes a single partition with all disk space"
265+
"Makes a single partition with all disk space (and makes it bootable if MBR)"
261266
disk.seek(0)
262267
SECTOR = options.get('phys_sector', 512)
263268
if fmt == 'mbr':
264269
part_size = disk.size
265270
if options.get('compatibility',1) == 0 and part_size > (2<<30): part_size = (2<<30)
266271
mbr = MBR(None, disksize=disk.size, sector=SECTOR)
272+
mbr.is_bootable = True
267273
if disk.type() == 'VHD':
268274
c, mbr.heads_per_cyl, mbr.sectors_per_cyl = struct.unpack('>HBB',disk.footer.dwDiskGeometry)
269275
elif disk.type() == 'VDI':
@@ -282,6 +288,7 @@ def partition(disk, fmt='gpt', options={}):
282288
else:
283289
options['mbr_type'] = mbr.partitions[0].bType
284290
if DEBUG&1: log("Made a MBR primary partition, type %X: %s", options['mbr_type'], mbr_types[options['mbr_type']])
291+
mbr.partitions[0].bStatus = 0x80 # mark as active (required by DOS)
285292
# Remove any previous GPT structure
286293
disk.write(32768*b'\x00')
287294
disk.seek(0)

FATtools/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '1.0.35'
1+
__version__ = '1.0.36'

nodos/MYMBR

151 Bytes
Binary file not shown.

nodos/MYMBR.ASM

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
; A generic Master Boot Record for IBM PC compatible
2+
; x86 16-bit boot code
3+
;
4+
; Works both with LBA and CHS partitions marked as bootable.
5+
;
6+
; compile with nasm mymbr.asm
7+
8+
; BIOS loads it at 7C00h, we relocate it to traditional address
9+
org 600h
10+
11+
; set DS=SS=ES=0 and SP=code origin
12+
xor cx, cx
13+
cli
14+
mov ss, cx
15+
mov sp, 7C00h
16+
mov ds, cx
17+
mov es, cx
18+
sti
19+
20+
mov bx, sp
21+
; relocate 512 bytes (100h words) to 600h
22+
mov si, bx
23+
mov di, 600h
24+
mov cx, 100h
25+
cld
26+
repe movsw
27+
; shorter?
28+
;push cx
29+
;push 0x61F
30+
;retf
31+
jmp 0x0000:0x61F ; jump to (relocated) next instruction
32+
33+
mov si, 7BEh ; partition table start at +1BEh (byte 80h/00h for bootable/not bootable)
34+
IsBootablePart:
35+
cmp byte [si], 80h
36+
jz LoadInt13_42H
37+
add si, 10h ; part. entry size
38+
cmp si, 7FEh
39+
jl IsBootablePart
40+
41+
PrintMsg:
42+
mov si, NoBoot
43+
PrintLoop:
44+
lodsb
45+
cmp al, 0
46+
jz Exit
47+
xor bx, bx
48+
mov ah, 0Eh ; output char in AL with attribute in BX
49+
int 10h
50+
jmp PrintLoop
51+
Exit:
52+
;int 18h ; diskless boot hook
53+
hlt
54+
jmp Exit
55+
56+
LoadInt13_42H:
57+
mov ah, 42h ; extended read in LBA mode from drive DL (preset by BIOS)
58+
xchg di, si
59+
mov si, dap ; disk address packet
60+
mov cx, [di+8] ; put LBA sector to read (LO-HI bytes) into dap
61+
mov [si + DAP.LBAlo], cx
62+
mov cx, [di+10]
63+
mov [si + DAP.LBAhi], cx
64+
; stc
65+
int 13h
66+
xchg di, si ; partition pointer back to SI
67+
jnc CheckMagic ; else, try with CHS read
68+
69+
struc DAP
70+
.size : resb 1
71+
.unused : resb 1
72+
.sectors : resw 1
73+
.buffer : resd 1
74+
.LBAlo : resd 1
75+
.LBAhi : resd 1
76+
endstruc
77+
78+
dap:
79+
istruc DAP
80+
at DAP.size, db 16
81+
at DAP.unused, db 0
82+
at DAP.sectors, dw 1 ; how many
83+
at DAP.buffer, dd 00007C00h ; buffer address (0000:7C00h)
84+
at DAP.LBAlo, dd 0 ; which sector?
85+
at DAP.LBAhi, dd 0
86+
iend
87+
88+
LoadInt13_02H:
89+
mov ax, 0201h ; read 1 sector from drive DL, C-H-S in CH-DH-CL, to ES:BX
90+
;mov bx, 7C00h ; pre-loaded above
91+
mov cx, [si+2] ; C-H-S in partition entry
92+
mov dh, [si+1]
93+
; stc
94+
int 13h
95+
jc PrintMsg
96+
CheckMagic:
97+
cmp word [7FEh], 0xAA55 ; magic in last sector word?
98+
jnz PrintMsg
99+
jmp 0x0000:0x7C00 ; jump to Boot Sector code, with DL=boot drive and DS:SI=partition booted
100+
101+
NoBoot:
102+
db "Nothing to boot.", 0

nodos/mymbr.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print ("Stringifying MBR code...\n", ''.join(['\\x%02X' % c for c in open('mymbr','rb').read()]))

0 commit comments

Comments
 (0)