diff options
author | Ed Bartosh <ed.bartosh@linux.intel.com> | 2017-02-09 16:28:54 +0200 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-02-15 20:06:44 -0800 |
commit | cdcc6e27530f13531b3bda9a15dc926f6ff9a837 (patch) | |
tree | a1993d5b949cde736661ffae78d55ac1b485eaa4 | |
parent | adf5e2956ca4e3136be0ee785115a7e1941a135b (diff) | |
download | poky-cdcc6e27530f13531b3bda9a15dc926f6ff9a837.tar.gz |
wic: move PartitionedImage class to direct.py
As PartitionedImage is only used in direct.py it makes sense
to move it there. It's easier to maintain (and refactor) it
this way.
(From OE-Core rev: 2550622371f5c50857e5d58eabab01a1823c6fc3)
Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | scripts/lib/wic/plugins/imager/direct.py | 278 | ||||
-rw-r--r-- | scripts/lib/wic/utils/partitionedfs.py | 301 |
2 files changed, 276 insertions, 303 deletions
diff --git a/scripts/lib/wic/plugins/imager/direct.py b/scripts/lib/wic/plugins/imager/direct.py index fefe88e0df..12044318e8 100644 --- a/scripts/lib/wic/plugins/imager/direct.py +++ b/scripts/lib/wic/plugins/imager/direct.py | |||
@@ -31,13 +31,12 @@ import tempfile | |||
31 | from time import strftime | 31 | from time import strftime |
32 | 32 | ||
33 | from wic import msger | 33 | from wic import msger |
34 | from wic.filemap import sparse_copy | ||
34 | from wic.ksparser import KickStart, KickStartError | 35 | from wic.ksparser import KickStart, KickStartError |
35 | from wic.plugin import pluginmgr | 36 | from wic.plugin import pluginmgr |
36 | from wic.pluginbase import ImagerPlugin | 37 | from wic.pluginbase import ImagerPlugin |
37 | from wic.utils.errors import CreatorError, ImageError | 38 | from wic.utils.errors import CreatorError, ImageError |
38 | from wic.utils.misc import get_bitbake_var, exec_cmd, exec_native_cmd | 39 | from wic.utils.misc import get_bitbake_var, exec_cmd, exec_native_cmd |
39 | from wic.utils.partitionedfs import PartitionedImage | ||
40 | |||
41 | 40 | ||
42 | class DirectPlugin(ImagerPlugin): | 41 | class DirectPlugin(ImagerPlugin): |
43 | """ | 42 | """ |
@@ -316,3 +315,278 @@ class DirectPlugin(ImagerPlugin): | |||
316 | 315 | ||
317 | # remove work directory | 316 | # remove work directory |
318 | shutil.rmtree(self.workdir, ignore_errors=True) | 317 | shutil.rmtree(self.workdir, ignore_errors=True) |
318 | |||
319 | # Overhead of the MBR partitioning scheme (just one sector) | ||
320 | MBR_OVERHEAD = 1 | ||
321 | |||
322 | # Overhead of the GPT partitioning scheme | ||
323 | GPT_OVERHEAD = 34 | ||
324 | |||
325 | # Size of a sector in bytes | ||
326 | SECTOR_SIZE = 512 | ||
327 | |||
328 | class PartitionedImage(): | ||
329 | """ | ||
330 | Partitioned image in a file. | ||
331 | """ | ||
332 | |||
333 | def __init__(self, path, ptable_format, native_sysroot=None): | ||
334 | self.path = path # Path to the image file | ||
335 | self.numpart = 0 # Number of allocated partitions | ||
336 | self.realpart = 0 # Number of partitions in the partition table | ||
337 | self.offset = 0 # Offset of next partition (in sectors) | ||
338 | self.min_size = 0 # Minimum required disk size to fit | ||
339 | # all partitions (in bytes) | ||
340 | self.ptable_format = ptable_format # Partition table format | ||
341 | # Disk system identifier | ||
342 | self.identifier = int.from_bytes(os.urandom(4), 'little') | ||
343 | |||
344 | self.partitions = [] | ||
345 | self.partimages = [] | ||
346 | # Size of a sector used in calculations | ||
347 | self.sector_size = SECTOR_SIZE | ||
348 | self.native_sysroot = native_sysroot | ||
349 | |||
350 | def add_partition(self, part): | ||
351 | """ | ||
352 | Add the next partition. Partitions have to be added in the | ||
353 | first-to-last order. | ||
354 | """ | ||
355 | part.ks_pnum = len(self.partitions) | ||
356 | |||
357 | # Converting kB to sectors for parted | ||
358 | part.size_sec = part.disk_size * 1024 // self.sector_size | ||
359 | |||
360 | self.partitions.append(part) | ||
361 | |||
362 | def layout_partitions(self): | ||
363 | """ Layout the partitions, meaning calculate the position of every | ||
364 | partition on the disk. The 'ptable_format' parameter defines the | ||
365 | partition table format and may be "msdos". """ | ||
366 | |||
367 | msger.debug("Assigning %s partitions to disks" % self.ptable_format) | ||
368 | |||
369 | # Go through partitions in the order they are added in .ks file | ||
370 | for num in range(len(self.partitions)): | ||
371 | part = self.partitions[num] | ||
372 | |||
373 | if self.ptable_format == 'msdos' and part.part_type: | ||
374 | # The --part-type can also be implemented for MBR partitions, | ||
375 | # in which case it would map to the 1-byte "partition type" | ||
376 | # filed at offset 3 of the partition entry. | ||
377 | raise ImageError("setting custom partition type is not " \ | ||
378 | "implemented for msdos partitions") | ||
379 | |||
380 | # Get the disk where the partition is located | ||
381 | self.numpart += 1 | ||
382 | if not part.no_table: | ||
383 | self.realpart += 1 | ||
384 | |||
385 | if self.numpart == 1: | ||
386 | if self.ptable_format == "msdos": | ||
387 | overhead = MBR_OVERHEAD | ||
388 | elif self.ptable_format == "gpt": | ||
389 | overhead = GPT_OVERHEAD | ||
390 | |||
391 | # Skip one sector required for the partitioning scheme overhead | ||
392 | self.offset += overhead | ||
393 | |||
394 | if self.realpart > 3: | ||
395 | # Reserve a sector for EBR for every logical partition | ||
396 | # before alignment is performed. | ||
397 | if self.ptable_format == "msdos": | ||
398 | self.offset += 1 | ||
399 | |||
400 | if part.align: | ||
401 | # If not first partition and we do have alignment set we need | ||
402 | # to align the partition. | ||
403 | # FIXME: This leaves a empty spaces to the disk. To fill the | ||
404 | # gaps we could enlargea the previous partition? | ||
405 | |||
406 | # Calc how much the alignment is off. | ||
407 | align_sectors = self.offset % (part.align * 1024 // self.sector_size) | ||
408 | |||
409 | if align_sectors: | ||
410 | # If partition is not aligned as required, we need | ||
411 | # to move forward to the next alignment point | ||
412 | align_sectors = (part.align * 1024 // self.sector_size) - align_sectors | ||
413 | |||
414 | msger.debug("Realignment for %s%s with %s sectors, original" | ||
415 | " offset %s, target alignment is %sK." % | ||
416 | (part.disk, self.numpart, align_sectors, | ||
417 | self.offset, part.align)) | ||
418 | |||
419 | # increase the offset so we actually start the partition on right alignment | ||
420 | self.offset += align_sectors | ||
421 | |||
422 | part.start = self.offset | ||
423 | self.offset += part.size_sec | ||
424 | |||
425 | part.type = 'primary' | ||
426 | if not part.no_table: | ||
427 | part.num = self.realpart | ||
428 | else: | ||
429 | part.num = 0 | ||
430 | |||
431 | if self.ptable_format == "msdos": | ||
432 | # only count the partitions that are in partition table | ||
433 | if len([p for p in self.partitions if not p.no_table]) > 4: | ||
434 | if self.realpart > 3: | ||
435 | part.type = 'logical' | ||
436 | part.num = self.realpart + 1 | ||
437 | |||
438 | msger.debug("Assigned %s to %s%d, sectors range %d-%d size %d " | ||
439 | "sectors (%d bytes)." \ | ||
440 | % (part.mountpoint, part.disk, part.num, | ||
441 | part.start, self.offset - 1, | ||
442 | part.size_sec, part.size_sec * self.sector_size)) | ||
443 | |||
444 | # Once all the partitions have been layed out, we can calculate the | ||
445 | # minumim disk size | ||
446 | self.min_size = self.offset | ||
447 | if self.ptable_format == "gpt": | ||
448 | self.min_size += GPT_OVERHEAD | ||
449 | |||
450 | self.min_size *= self.sector_size | ||
451 | |||
452 | def _create_partition(self, device, parttype, fstype, start, size): | ||
453 | """ Create a partition on an image described by the 'device' object. """ | ||
454 | |||
455 | # Start is included to the size so we need to substract one from the end. | ||
456 | end = start + size - 1 | ||
457 | msger.debug("Added '%s' partition, sectors %d-%d, size %d sectors" % | ||
458 | (parttype, start, end, size)) | ||
459 | |||
460 | cmd = "parted -s %s unit s mkpart %s" % (device, parttype) | ||
461 | if fstype: | ||
462 | cmd += " %s" % fstype | ||
463 | cmd += " %d %d" % (start, end) | ||
464 | |||
465 | return exec_native_cmd(cmd, self.native_sysroot) | ||
466 | |||
467 | def create(self): | ||
468 | msger.debug("Creating sparse file %s" % self.path) | ||
469 | with open(self.path, 'w') as sparse: | ||
470 | os.ftruncate(sparse.fileno(), self.min_size) | ||
471 | |||
472 | msger.debug("Initializing partition table for %s" % self.path) | ||
473 | exec_native_cmd("parted -s %s mklabel %s" % | ||
474 | (self.path, self.ptable_format), self.native_sysroot) | ||
475 | |||
476 | msger.debug("Set disk identifier %x" % self.identifier) | ||
477 | with open(self.path, 'r+b') as img: | ||
478 | img.seek(0x1B8) | ||
479 | img.write(self.identifier.to_bytes(4, 'little')) | ||
480 | |||
481 | msger.debug("Creating partitions") | ||
482 | |||
483 | for part in self.partitions: | ||
484 | if part.num == 0: | ||
485 | continue | ||
486 | |||
487 | if self.ptable_format == "msdos" and part.num == 5: | ||
488 | # Create an extended partition (note: extended | ||
489 | # partition is described in MBR and contains all | ||
490 | # logical partitions). The logical partitions save a | ||
491 | # sector for an EBR just before the start of a | ||
492 | # partition. The extended partition must start one | ||
493 | # sector before the start of the first logical | ||
494 | # partition. This way the first EBR is inside of the | ||
495 | # extended partition. Since the extended partitions | ||
496 | # starts a sector before the first logical partition, | ||
497 | # add a sector at the back, so that there is enough | ||
498 | # room for all logical partitions. | ||
499 | self._create_partition(self.path, "extended", | ||
500 | None, part.start - 1, | ||
501 | self.offset - part.start + 1) | ||
502 | |||
503 | if part.fstype == "swap": | ||
504 | parted_fs_type = "linux-swap" | ||
505 | elif part.fstype == "vfat": | ||
506 | parted_fs_type = "fat32" | ||
507 | elif part.fstype == "msdos": | ||
508 | parted_fs_type = "fat16" | ||
509 | elif part.fstype == "ontrackdm6aux3": | ||
510 | parted_fs_type = "ontrackdm6aux3" | ||
511 | else: | ||
512 | # Type for ext2/ext3/ext4/btrfs | ||
513 | parted_fs_type = "ext2" | ||
514 | |||
515 | # Boot ROM of OMAP boards require vfat boot partition to have an | ||
516 | # even number of sectors. | ||
517 | if part.mountpoint == "/boot" and part.fstype in ["vfat", "msdos"] \ | ||
518 | and part.size_sec % 2: | ||
519 | msger.debug("Subtracting one sector from '%s' partition to " \ | ||
520 | "get even number of sectors for the partition" % \ | ||
521 | part.mountpoint) | ||
522 | part.size_sec -= 1 | ||
523 | |||
524 | self._create_partition(self.path, part.type, | ||
525 | parted_fs_type, part.start, part.size_sec) | ||
526 | |||
527 | if part.part_type: | ||
528 | msger.debug("partition %d: set type UID to %s" % \ | ||
529 | (part.num, part.part_type)) | ||
530 | exec_native_cmd("sgdisk --typecode=%d:%s %s" % \ | ||
531 | (part.num, part.part_type, | ||
532 | self.path), self.native_sysroot) | ||
533 | |||
534 | if part.uuid and self.ptable_format == "gpt": | ||
535 | msger.debug("partition %d: set UUID to %s" % \ | ||
536 | (part.num, part.uuid)) | ||
537 | exec_native_cmd("sgdisk --partition-guid=%d:%s %s" % \ | ||
538 | (part.num, part.uuid, self.path), | ||
539 | self.native_sysroot) | ||
540 | |||
541 | if part.label and self.ptable_format == "gpt": | ||
542 | msger.debug("partition %d: set name to %s" % \ | ||
543 | (part.num, part.label)) | ||
544 | exec_native_cmd("parted -s %s name %d %s" % \ | ||
545 | (self.path, part.num, part.label), | ||
546 | self.native_sysroot) | ||
547 | |||
548 | if part.active: | ||
549 | flag_name = "legacy_boot" if self.ptable_format == 'gpt' else "boot" | ||
550 | msger.debug("Set '%s' flag for partition '%s' on disk '%s'" % \ | ||
551 | (flag_name, part.num, self.path)) | ||
552 | exec_native_cmd("parted -s %s set %d %s on" % \ | ||
553 | (self.path, part.num, flag_name), | ||
554 | self.native_sysroot) | ||
555 | if part.system_id: | ||
556 | exec_native_cmd("sfdisk --part-type %s %s %s" % \ | ||
557 | (self.path, part.num, part.system_id), | ||
558 | self.native_sysroot) | ||
559 | |||
560 | # Parted defaults to enabling the lba flag for fat16 partitions, | ||
561 | # which causes compatibility issues with some firmware (and really | ||
562 | # isn't necessary). | ||
563 | if parted_fs_type == "fat16": | ||
564 | if self.ptable_format == 'msdos': | ||
565 | msger.debug("Disable 'lba' flag for partition '%s' on disk '%s'" % \ | ||
566 | (part.num, self.path)) | ||
567 | exec_native_cmd("parted -s %s set %d lba off" % \ | ||
568 | (self.path, part.num), | ||
569 | self.native_sysroot) | ||
570 | |||
571 | def cleanup(self): | ||
572 | # remove partition images | ||
573 | for image in self.partimages: | ||
574 | os.remove(image) | ||
575 | |||
576 | def assemble(self): | ||
577 | msger.debug("Installing partitions") | ||
578 | |||
579 | for part in self.partitions: | ||
580 | source = part.source_file | ||
581 | if source: | ||
582 | # install source_file contents into a partition | ||
583 | sparse_copy(source, self.path, part.start * self.sector_size) | ||
584 | |||
585 | msger.debug("Installed %s in partition %d, sectors %d-%d, " | ||
586 | "size %d sectors" % \ | ||
587 | (source, part.num, part.start, | ||
588 | part.start + part.size_sec - 1, part.size_sec)) | ||
589 | |||
590 | partimage = self.path + '.p%d' % part.num | ||
591 | os.rename(source, partimage) | ||
592 | self.partimages.append(partimage) | ||
diff --git a/scripts/lib/wic/utils/partitionedfs.py b/scripts/lib/wic/utils/partitionedfs.py deleted file mode 100644 index cdf8f08015..0000000000 --- a/scripts/lib/wic/utils/partitionedfs.py +++ /dev/null | |||
@@ -1,301 +0,0 @@ | |||
1 | #!/usr/bin/env python -tt | ||
2 | # | ||
3 | # Copyright (c) 2009, 2010, 2011 Intel, Inc. | ||
4 | # Copyright (c) 2007, 2008 Red Hat, Inc. | ||
5 | # Copyright (c) 2008 Daniel P. Berrange | ||
6 | # Copyright (c) 2008 David P. Huff | ||
7 | # | ||
8 | # This program is free software; you can redistribute it and/or modify it | ||
9 | # under the terms of the GNU General Public License as published by the Free | ||
10 | # Software Foundation; version 2 of the License | ||
11 | # | ||
12 | # This program is distributed in the hope that it will be useful, but | ||
13 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
14 | # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
15 | # for more details. | ||
16 | # | ||
17 | # You should have received a copy of the GNU General Public License along | ||
18 | # with this program; if not, write to the Free Software Foundation, Inc., 59 | ||
19 | # Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
20 | |||
21 | import os | ||
22 | |||
23 | from wic import msger | ||
24 | from wic.utils.errors import ImageError | ||
25 | from wic.utils.misc import exec_native_cmd | ||
26 | from wic.filemap import sparse_copy | ||
27 | |||
28 | # Overhead of the MBR partitioning scheme (just one sector) | ||
29 | MBR_OVERHEAD = 1 | ||
30 | |||
31 | # Overhead of the GPT partitioning scheme | ||
32 | GPT_OVERHEAD = 34 | ||
33 | |||
34 | # Size of a sector in bytes | ||
35 | SECTOR_SIZE = 512 | ||
36 | |||
37 | class PartitionedImage(): | ||
38 | """ | ||
39 | Partitioned image in a file. | ||
40 | """ | ||
41 | |||
42 | def __init__(self, path, ptable_format, native_sysroot=None): | ||
43 | self.path = path # Path to the image file | ||
44 | self.numpart = 0 # Number of allocated partitions | ||
45 | self.realpart = 0 # Number of partitions in the partition table | ||
46 | self.offset = 0 # Offset of next partition (in sectors) | ||
47 | self.min_size = 0 # Minimum required disk size to fit | ||
48 | # all partitions (in bytes) | ||
49 | self.ptable_format = ptable_format # Partition table format | ||
50 | # Disk system identifier | ||
51 | self.identifier = int.from_bytes(os.urandom(4), 'little') | ||
52 | |||
53 | self.partitions = [] | ||
54 | self.partimages = [] | ||
55 | # Size of a sector used in calculations | ||
56 | self.sector_size = SECTOR_SIZE | ||
57 | self.native_sysroot = native_sysroot | ||
58 | |||
59 | def add_partition(self, part): | ||
60 | """ | ||
61 | Add the next partition. Partitions have to be added in the | ||
62 | first-to-last order. | ||
63 | """ | ||
64 | part.ks_pnum = len(self.partitions) | ||
65 | |||
66 | # Converting kB to sectors for parted | ||
67 | part.size_sec = part.disk_size * 1024 // self.sector_size | ||
68 | |||
69 | self.partitions.append(part) | ||
70 | |||
71 | def layout_partitions(self): | ||
72 | """ Layout the partitions, meaning calculate the position of every | ||
73 | partition on the disk. The 'ptable_format' parameter defines the | ||
74 | partition table format and may be "msdos". """ | ||
75 | |||
76 | msger.debug("Assigning %s partitions to disks" % self.ptable_format) | ||
77 | |||
78 | # Go through partitions in the order they are added in .ks file | ||
79 | for num in range(len(self.partitions)): | ||
80 | part = self.partitions[num] | ||
81 | |||
82 | if self.ptable_format == 'msdos' and part.part_type: | ||
83 | # The --part-type can also be implemented for MBR partitions, | ||
84 | # in which case it would map to the 1-byte "partition type" | ||
85 | # filed at offset 3 of the partition entry. | ||
86 | raise ImageError("setting custom partition type is not " \ | ||
87 | "implemented for msdos partitions") | ||
88 | |||
89 | # Get the disk where the partition is located | ||
90 | self.numpart += 1 | ||
91 | if not part.no_table: | ||
92 | self.realpart += 1 | ||
93 | |||
94 | if self.numpart == 1: | ||
95 | if self.ptable_format == "msdos": | ||
96 | overhead = MBR_OVERHEAD | ||
97 | elif self.ptable_format == "gpt": | ||
98 | overhead = GPT_OVERHEAD | ||
99 | |||
100 | # Skip one sector required for the partitioning scheme overhead | ||
101 | self.offset += overhead | ||
102 | |||
103 | if self.realpart > 3: | ||
104 | # Reserve a sector for EBR for every logical partition | ||
105 | # before alignment is performed. | ||
106 | if self.ptable_format == "msdos": | ||
107 | self.offset += 1 | ||
108 | |||
109 | if part.align: | ||
110 | # If not first partition and we do have alignment set we need | ||
111 | # to align the partition. | ||
112 | # FIXME: This leaves a empty spaces to the disk. To fill the | ||
113 | # gaps we could enlargea the previous partition? | ||
114 | |||
115 | # Calc how much the alignment is off. | ||
116 | align_sectors = self.offset % (part.align * 1024 // self.sector_size) | ||
117 | |||
118 | if align_sectors: | ||
119 | # If partition is not aligned as required, we need | ||
120 | # to move forward to the next alignment point | ||
121 | align_sectors = (part.align * 1024 // self.sector_size) - align_sectors | ||
122 | |||
123 | msger.debug("Realignment for %s%s with %s sectors, original" | ||
124 | " offset %s, target alignment is %sK." % | ||
125 | (part.disk, self.numpart, align_sectors, | ||
126 | self.offset, part.align)) | ||
127 | |||
128 | # increase the offset so we actually start the partition on right alignment | ||
129 | self.offset += align_sectors | ||
130 | |||
131 | part.start = self.offset | ||
132 | self.offset += part.size_sec | ||
133 | |||
134 | part.type = 'primary' | ||
135 | if not part.no_table: | ||
136 | part.num = self.realpart | ||
137 | else: | ||
138 | part.num = 0 | ||
139 | |||
140 | if self.ptable_format == "msdos": | ||
141 | # only count the partitions that are in partition table | ||
142 | if len([p for p in self.partitions if not p.no_table]) > 4: | ||
143 | if self.realpart > 3: | ||
144 | part.type = 'logical' | ||
145 | part.num = self.realpart + 1 | ||
146 | |||
147 | msger.debug("Assigned %s to %s%d, sectors range %d-%d size %d " | ||
148 | "sectors (%d bytes)." \ | ||
149 | % (part.mountpoint, part.disk, part.num, | ||
150 | part.start, self.offset - 1, | ||
151 | part.size_sec, part.size_sec * self.sector_size)) | ||
152 | |||
153 | # Once all the partitions have been layed out, we can calculate the | ||
154 | # minumim disk size | ||
155 | self.min_size = self.offset | ||
156 | if self.ptable_format == "gpt": | ||
157 | self.min_size += GPT_OVERHEAD | ||
158 | |||
159 | self.min_size *= self.sector_size | ||
160 | |||
161 | def _create_partition(self, device, parttype, fstype, start, size): | ||
162 | """ Create a partition on an image described by the 'device' object. """ | ||
163 | |||
164 | # Start is included to the size so we need to substract one from the end. | ||
165 | end = start + size - 1 | ||
166 | msger.debug("Added '%s' partition, sectors %d-%d, size %d sectors" % | ||
167 | (parttype, start, end, size)) | ||
168 | |||
169 | cmd = "parted -s %s unit s mkpart %s" % (device, parttype) | ||
170 | if fstype: | ||
171 | cmd += " %s" % fstype | ||
172 | cmd += " %d %d" % (start, end) | ||
173 | |||
174 | return exec_native_cmd(cmd, self.native_sysroot) | ||
175 | |||
176 | def create(self): | ||
177 | msger.debug("Creating sparse file %s" % self.path) | ||
178 | with open(self.path, 'w') as sparse: | ||
179 | os.ftruncate(sparse.fileno(), self.min_size) | ||
180 | |||
181 | msger.debug("Initializing partition table for %s" % self.path) | ||
182 | exec_native_cmd("parted -s %s mklabel %s" % | ||
183 | (self.path, self.ptable_format), self.native_sysroot) | ||
184 | |||
185 | msger.debug("Set disk identifier %x" % self.identifier) | ||
186 | with open(self.path, 'r+b') as img: | ||
187 | img.seek(0x1B8) | ||
188 | img.write(self.identifier.to_bytes(4, 'little')) | ||
189 | |||
190 | msger.debug("Creating partitions") | ||
191 | |||
192 | for part in self.partitions: | ||
193 | if part.num == 0: | ||
194 | continue | ||
195 | |||
196 | if self.ptable_format == "msdos" and part.num == 5: | ||
197 | # Create an extended partition (note: extended | ||
198 | # partition is described in MBR and contains all | ||
199 | # logical partitions). The logical partitions save a | ||
200 | # sector for an EBR just before the start of a | ||
201 | # partition. The extended partition must start one | ||
202 | # sector before the start of the first logical | ||
203 | # partition. This way the first EBR is inside of the | ||
204 | # extended partition. Since the extended partitions | ||
205 | # starts a sector before the first logical partition, | ||
206 | # add a sector at the back, so that there is enough | ||
207 | # room for all logical partitions. | ||
208 | self._create_partition(self.path, "extended", | ||
209 | None, part.start - 1, | ||
210 | self.offset - part.start + 1) | ||
211 | |||
212 | if part.fstype == "swap": | ||
213 | parted_fs_type = "linux-swap" | ||
214 | elif part.fstype == "vfat": | ||
215 | parted_fs_type = "fat32" | ||
216 | elif part.fstype == "msdos": | ||
217 | parted_fs_type = "fat16" | ||
218 | elif part.fstype == "ontrackdm6aux3": | ||
219 | parted_fs_type = "ontrackdm6aux3" | ||
220 | else: | ||
221 | # Type for ext2/ext3/ext4/btrfs | ||
222 | parted_fs_type = "ext2" | ||
223 | |||
224 | # Boot ROM of OMAP boards require vfat boot partition to have an | ||
225 | # even number of sectors. | ||
226 | if part.mountpoint == "/boot" and part.fstype in ["vfat", "msdos"] \ | ||
227 | and part.size_sec % 2: | ||
228 | msger.debug("Subtracting one sector from '%s' partition to " \ | ||
229 | "get even number of sectors for the partition" % \ | ||
230 | part.mountpoint) | ||
231 | part.size_sec -= 1 | ||
232 | |||
233 | self._create_partition(self.path, part.type, | ||
234 | parted_fs_type, part.start, part.size_sec) | ||
235 | |||
236 | if part.part_type: | ||
237 | msger.debug("partition %d: set type UID to %s" % \ | ||
238 | (part.num, part.part_type)) | ||
239 | exec_native_cmd("sgdisk --typecode=%d:%s %s" % \ | ||
240 | (part.num, part.part_type, | ||
241 | self.path), self.native_sysroot) | ||
242 | |||
243 | if part.uuid and self.ptable_format == "gpt": | ||
244 | msger.debug("partition %d: set UUID to %s" % \ | ||
245 | (part.num, part.uuid)) | ||
246 | exec_native_cmd("sgdisk --partition-guid=%d:%s %s" % \ | ||
247 | (part.num, part.uuid, self.path), | ||
248 | self.native_sysroot) | ||
249 | |||
250 | if part.label and self.ptable_format == "gpt": | ||
251 | msger.debug("partition %d: set name to %s" % \ | ||
252 | (part.num, part.label)) | ||
253 | exec_native_cmd("parted -s %s name %d %s" % \ | ||
254 | (self.path, part.num, part.label), | ||
255 | self.native_sysroot) | ||
256 | |||
257 | if part.active: | ||
258 | flag_name = "legacy_boot" if self.ptable_format == 'gpt' else "boot" | ||
259 | msger.debug("Set '%s' flag for partition '%s' on disk '%s'" % \ | ||
260 | (flag_name, part.num, self.path)) | ||
261 | exec_native_cmd("parted -s %s set %d %s on" % \ | ||
262 | (self.path, part.num, flag_name), | ||
263 | self.native_sysroot) | ||
264 | if part.system_id: | ||
265 | exec_native_cmd("sfdisk --part-type %s %s %s" % \ | ||
266 | (self.path, part.num, part.system_id), | ||
267 | self.native_sysroot) | ||
268 | |||
269 | # Parted defaults to enabling the lba flag for fat16 partitions, | ||
270 | # which causes compatibility issues with some firmware (and really | ||
271 | # isn't necessary). | ||
272 | if parted_fs_type == "fat16": | ||
273 | if self.ptable_format == 'msdos': | ||
274 | msger.debug("Disable 'lba' flag for partition '%s' on disk '%s'" % \ | ||
275 | (part.num, self.path)) | ||
276 | exec_native_cmd("parted -s %s set %d lba off" % \ | ||
277 | (self.path, part.num), | ||
278 | self.native_sysroot) | ||
279 | |||
280 | def cleanup(self): | ||
281 | # remove partition images | ||
282 | for image in self.partimages: | ||
283 | os.remove(image) | ||
284 | |||
285 | def assemble(self): | ||
286 | msger.debug("Installing partitions") | ||
287 | |||
288 | for part in self.partitions: | ||
289 | source = part.source_file | ||
290 | if source: | ||
291 | # install source_file contents into a partition | ||
292 | sparse_copy(source, self.path, part.start * self.sector_size) | ||
293 | |||
294 | msger.debug("Installed %s in partition %d, sectors %d-%d, " | ||
295 | "size %d sectors" % \ | ||
296 | (source, part.num, part.start, | ||
297 | part.start + part.size_sec - 1, part.size_sec)) | ||
298 | |||
299 | partimage = self.path + '.p%d' % part.num | ||
300 | os.rename(source, partimage) | ||
301 | self.partimages.append(partimage) | ||