Revision b50c8289 snf-image-helper/disklabel.py
b/snf-image-helper/disklabel.py | ||
---|---|---|
98 | 98 |
def pack_chs(cylinder, head, sector): |
99 | 99 |
"""Packs a CHS tuple to an address string.""" |
100 | 100 |
|
101 |
assert 1 <= sector <= 63 |
|
102 |
assert 0 <= head <= 255 |
|
103 |
assert 0 <= cylinder |
|
104 |
|
|
105 |
# If the cylinders overflow then put the value (1023, 254, 63) to |
|
106 |
# the tuple. At least this is what OpenBSD does. |
|
107 |
if cylinder > 1023: |
|
108 |
cylinder = 1023 |
|
109 |
head = 254 |
|
110 |
sector = 63 |
|
101 |
assert 1 <= sector < 2**6, "Invalid sector value" |
|
102 |
assert 0 <= head < 2**8, "Invalid head value" |
|
103 |
assert 0 <= cylinder < 2**10, "Invalid cylinder value" |
|
111 | 104 |
|
112 | 105 |
byte0 = head |
113 | 106 |
byte1 = (cylinder >> 2) & 0xC0 | sector |
... | ... | |
209 | 202 |
start = self.mbr.part[self.part_num].first_sector |
210 | 203 |
self.mbr.part[self.part_num].sector_count = end - start + 1 |
211 | 204 |
|
212 |
ntracks = self.disklabel.field['ntracks'] |
|
213 |
nsectors = self.disklabel.field['nsectors'] |
|
205 |
# There are cases where the CHS address changes although the LBA |
|
206 |
# address remains the same. For example when the bios is configured |
|
207 |
# to use a disk in LBA-Assisted translation mode, the CHS |
|
208 |
# representation depends on the size of the disk. When we enlarge the |
|
209 |
# size of the disk we may have to update the starting sector's CHS |
|
210 |
# address too. |
|
211 |
start_chs = MBR.Partition.pack_chs(*self.disklabel.lba2chs(start)) |
|
212 |
self.mbr.part[self.part_num].start = start_chs |
|
214 | 213 |
|
215 |
cylinder = end // (ntracks * nsectors) |
|
216 |
header = (end // nsectors) % ntracks |
|
217 |
sector = (end % nsectors) + 1 |
|
218 |
chs = MBR.Partition.pack_chs(cylinder, header, sector) |
|
219 |
self.mbr.part[self.part_num].end = chs |
|
214 |
end_chs = MBR.Partition.pack_chs(*self.disklabel.lba2chs(end)) |
|
215 |
self.mbr.part[self.part_num].end = end_chs |
|
220 | 216 |
|
221 | 217 |
def enlarge_last_partition(self): |
222 | 218 |
"""Enlarge the last partition to cover up all the free space""" |
... | ... | |
277 | 273 |
|
278 | 274 |
return checksum |
279 | 275 |
|
280 |
@abc.abstractmethod |
|
281 |
def enlarge(self, new_size): |
|
282 |
"""Enlarge the disk and return the last usable sector""" |
|
283 |
pass |
|
284 |
|
|
285 | 276 |
def write_to(self, device): |
286 | 277 |
"""Write the disklabel to a device""" |
287 | 278 |
|
... | ... | |
289 | 280 |
device.seek(BLOCKSIZE, os.SEEK_CUR) |
290 | 281 |
device.write(self.pack()) |
291 | 282 |
|
283 |
def lba2chs(self, lba, hpc=None, spt=None): |
|
284 |
"""Returns the CHS address for a given LBA address""" |
|
285 |
|
|
286 |
assert hpc is None or hpc > 0, "Invalid heads per cylinder value" |
|
287 |
assert spt is None or spt > 0, "Invalid sectors per track value" |
|
288 |
|
|
289 |
if hpc is None: |
|
290 |
hpc = self.field['ntracks'] |
|
291 |
|
|
292 |
if spt is None: |
|
293 |
spt = self.field['nsectors'] |
|
294 |
|
|
295 |
# See: |
|
296 |
# http://en.wikipedia.org/wiki/Logical_Block_Addressing#CHS_conversion |
|
297 |
# |
|
298 |
|
|
299 |
cylinder = lba // (spt * hpc) |
|
300 |
header = (lba // spt) % hpc |
|
301 |
sector = (lba % spt) + 1 |
|
302 |
|
|
303 |
return (cylinder, header, sector) |
|
304 |
|
|
305 |
@abc.abstractmethod |
|
306 |
def enlarge(self, new_size): |
|
307 |
"""Enlarge the disk and return the last usable sector""" |
|
308 |
pass |
|
309 |
|
|
292 | 310 |
@abc.abstractmethod |
293 | 311 |
def enlarge_last_partition(self): |
294 | 312 |
"""Enlarge the last partition to consume all the usable space""" |
... | ... | |
484 | 502 |
|
485 | 503 |
@property |
486 | 504 |
def fields(self): |
487 |
return [ # Offset Length Contents |
|
505 |
return [ # Offset Length Contents
|
|
488 | 506 |
'size', # 0 4 Number of sectors in the partition |
489 | 507 |
'offset', # 4 4 Starting sector of the partition |
490 | 508 |
'offseth', # 8 2 Starting sector (high part) |
... | ... | |
655 | 673 |
|
656 | 674 |
self.field['checksum'] = self.compute_checksum() |
657 | 675 |
|
676 |
def lba2chs(self, lba, hpc=None, spt=None): |
|
677 |
"""Returns the CHS address for a given LBA address""" |
|
678 |
|
|
679 |
chs = super(OpenBSDDisklabel, self).lba2chs(lba, hpc, spt) |
|
680 |
|
|
681 |
# If the cylinders overflow, then OpenBSD will put the value |
|
682 |
#(1023, 254, 63) to the tuple. |
|
683 |
if chs[0] > 1023: |
|
684 |
return (1023, 254, 63) |
|
685 |
|
|
686 |
return chs |
|
687 |
|
|
658 | 688 |
def __str__(self): |
659 | 689 |
"""Print the Disklabel""" |
660 | 690 |
|
Also available in: Unified diff