diff options
author | Semen Protsenko <semen.protsenko@linaro.org> | 2014-06-04 11:11:04 +0100 |
---|---|---|
committer | Fathi Boudra <fathi.boudra@linaro.org> | 2014-06-14 12:21:00 +0000 |
commit | 0c28539742ead845da3c08bae63be5af9a71d0d7 (patch) | |
tree | c034a8cd2d482a679763ea6245a36270cbdb389c /linaro_image_tools | |
parent | 23231928b4e6d1d6df985defe9de4ee0e0f04db1 (diff) |
linaro-media-create: add GPT support (--part-table option)
Now user can choose partition table between MBR (default) or GPT, using
the option "--part-table". For GPT partitioning, "sgdisk" tool is required.
Call-chain of interest (before this patch):
linaro-media-create: __main__() ->
linaro_image_tools/media_create/partitions.py: setup_partitions() ->
linaro_image_tools/media_create/partitions.py: create_partitions() ->
linaro_image_tools/media_create/partitions.py: run_sfdisk_commands()
The same operation can be done manually as follows:
$ dd if=/dev/zero of=linaro.img bs=1M count=2k
$ /sbin/sgdisk -n 1:-:200m -t 1:EF00 linaro.img
$ /sbin/sgdisk -n 2:-:- -t 2:8300 linaro.img
$ sudo kpartx -a linaro.img
$ sudo mkfs.vfat -F32 -s 2 /dev/mapper/loop0p1
$ sudo mkfs.ext4 /dev/mapper/loop0p2
$ sudo kpartx -d linaro.img
Change-Id: Iba274c18bdb1f618124c8cc2784f233b049de7f0
Signed-off-by: Semen Protsenko <semen.protsenko@linaro.org>
Diffstat (limited to 'linaro_image_tools')
-rw-r--r-- | linaro_image_tools/media_create/__init__.py | 3 | ||||
-rw-r--r-- | linaro_image_tools/media_create/boards.py | 76 | ||||
-rw-r--r-- | linaro_image_tools/media_create/partitions.py | 49 | ||||
-rw-r--r-- | linaro_image_tools/media_create/tests/test_media_create.py | 5 |
4 files changed, 100 insertions, 33 deletions
diff --git a/linaro_image_tools/media_create/__init__.py b/linaro_image_tools/media_create/__init__.py index 3fda1bd..a69156d 100644 --- a/linaro_image_tools/media_create/__init__.py +++ b/linaro_image_tools/media_create/__init__.py @@ -103,6 +103,9 @@ def get_args_parser(): '--dev', dest='dev', choices=KNOWN_BOARDS, help='Generate an SD card or image for the given board.') parser.add_argument( + '--part-table', default='mbr', choices=['mbr', 'gpt'], + help='Type of partition table to use for the MMC image') + parser.add_argument( '--rootfs', default='ext4', choices=['ext2', 'ext3', 'ext4', 'btrfs'], help='Type of filesystem to use for the rootfs') parser.add_argument( diff --git a/linaro_image_tools/media_create/boards.py b/linaro_image_tools/media_create/boards.py index c208932..03294f4 100644 --- a/linaro_image_tools/media_create/boards.py +++ b/linaro_image_tools/media_create/boards.py @@ -453,15 +453,7 @@ class BoardConfig(object): # kill off hwpacks V1. return self.get_normal_sfdisk_cmd(should_align_boot_part) - def get_normal_sfdisk_cmd(self, should_align_boot_part=False): - """Return the sfdisk command to partition the media. - - :param should_align_boot_part: Whether to align the boot partition too. - - This returns a boot partition of type FAT16 or FAT32 or Linux, - followed by a root partition. - """ - + def get_normal_params(self, should_align_boot_part=False): if self.bootfs_type == 'vfat': if self.fat_size == 32: partition_type = '0x0C' @@ -493,6 +485,31 @@ class BoardConfig(object): root_start, _root_end, _root_len = align_partition( boot_end + 1, self.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S) + return (boot_start, boot_len, partition_type, root_start) + + def get_reserved_params(self, should_align_boot_part=None): + loader_start, loader_end, loader_len = align_partition( + self.loader_start_s, self.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S) + + boot_start, boot_end, boot_len = align_partition( + loader_end + 1, self.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S) + + root_start, _root_end, _root_len = align_partition( + boot_end + 1, self.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S) + + return (loader_start, loader_len, boot_start, boot_len, root_start) + + def get_normal_sfdisk_cmd(self, should_align_boot_part=False): + """Return the sfdisk command to partition the media. + + :param should_align_boot_part: Whether to align the boot partition too. + + This returns a boot partition of type FAT16 or FAT32 or Linux, + followed by a root partition. + """ + (boot_start, boot_len, partition_type, + root_start) = self.get_normal_params(should_align_boot_part) + return '%s,%s,%s,*\n%s,,,-' % ( boot_start, boot_len, partition_type, root_start) @@ -504,18 +521,31 @@ class BoardConfig(object): This returns a loader partition, then a boot vfat partition of type FAT16 or FAT32, followed by a root partition. """ - loader_start, loader_end, loader_len = align_partition( - self.loader_start_s, self.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S) - - boot_start, boot_end, boot_len = align_partition( - loader_end + 1, self.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S) - - root_start, _root_end, _root_len = align_partition( - boot_end + 1, self.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S) + (loader_start, loader_len, boot_start, boot_len, + root_start) = self.get_reserved_params(should_align_boot_part) return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % ( loader_start, loader_len, boot_start, boot_len, root_start) + def get_normal_sgdisk_cmd(self, should_align_boot_part=None): + (boot_start, boot_len, partition_type, + root_start) = self.get_normal_params(should_align_boot_part) + # Ignoring partition type because we need 0xEF for GPT + return '-n 1:%s:%s -t 1:EF00 ' \ + '-n 2:%s:- -t 2:8300' % (boot_start, boot_len, root_start) + + def get_reserved_sgdisk_cmd(self, should_align_boot_part=None): + """Return the sgdisk command to partition the media. + + :param should_align_boot_part: Ignored. + """ + (loader_start, loader_len, boot_start, boot_len, + root_start) = self.get_reserved_params(should_align_boot_part) + return '-n 1:%s:%s -t 1:DA00 ' \ + '-n 2:%s:%s -t 2:0C00 ' \ + '-n 3:%s:- -t 3:8300' % ( + loader_start, loader_len, boot_start, boot_len, root_start) + def get_sfdisk_cmd(self, should_align_boot_part=False): if (self.partition_layout in ['bootfs_rootfs', 'bootfs16_rootfs'] or self.board == 'snowball_sd'): @@ -528,6 +558,18 @@ class BoardConfig(object): "partition_layout is unspecified.") return self.get_v1_sfdisk_cmd(should_align_boot_part) + def get_sgdisk_cmd(self, should_align_boot_part=False): + if (self.partition_layout in ['bootfs_rootfs', 'bootfs16_rootfs'] or + self.board == 'snowball_sd'): + return self.get_normal_sgdisk_cmd(should_align_boot_part) + elif self.partition_layout in ['reserved_bootfs_rootfs']: + return self.get_reserved_sgdisk_cmd(should_align_boot_part) + else: + assert (self.hwpack_format == HardwarepackHandler.FORMAT_1), ( + "Hwpack format is not 1.0 but " + "partition_layout is unspecified.") + return self.get_normal_sgdisk_cmd(should_align_boot_part) + def _get_bootcmd(self, i_img_data, d_img_data): """Get the bootcmd for this board. diff --git a/linaro_image_tools/media_create/partitions.py b/linaro_image_tools/media_create/partitions.py index 9f881f5..0ee3a77 100644 --- a/linaro_image_tools/media_create/partitions.py +++ b/linaro_image_tools/media_create/partitions.py @@ -118,7 +118,7 @@ def setup_android_partitions(board_config, media, image_size, bootfs_label, def setup_partitions(board_config, media, image_size, bootfs_label, rootfs_label, rootfs_type, should_create_partitions, should_format_bootfs, should_format_rootfs, - should_align_boot_part=False): + should_align_boot_part=False, part_table="mbr"): """Make sure the given device is partitioned to boot the given board. :param board_config: A BoardConfig class. @@ -135,6 +135,7 @@ def setup_partitions(board_config, media, image_size, bootfs_label, :param should_format_rootfs: Whether to reuse the filesystem on the root partition. :param should_align_boot_part: Whether to align the boot partition too. + :param part_table: Type of partition table, either 'mbr' or 'gpt'. """ cylinders = None if not media.is_block_device: @@ -149,7 +150,8 @@ def setup_partitions(board_config, media, image_size, bootfs_label, if should_create_partitions: create_partitions( board_config, media, HEADS, SECTORS, cylinders, - should_align_boot_part=should_align_boot_part) + should_align_boot_part=should_align_boot_part, + part_table=part_table) if media.is_block_device: bootfs, rootfs = get_boot_and_root_partitions_for_media( @@ -556,8 +558,15 @@ def run_sfdisk_commands(commands, heads, sectors, cylinders, device, return proc.communicate("%s\n" % commands) +def run_sgdisk_commands(commands, device, as_root=True, stderr=None): + args = ['sgdisk', device] + args.extend(commands.split()) + proc = cmd_runner.run(args, stderr=stderr, as_root=as_root) + proc.wait() + + def create_partitions(board_config, media, heads, sectors, cylinders=None, - should_align_boot_part=False): + should_align_boot_part=False, part_table="mbr"): """Partition the given media according to the board requirements. :param board_config: A BoardConfig class. @@ -569,26 +578,37 @@ def create_partitions(board_config, media, heads, sectors, cylinders=None, :param cylinders: The number of cylinders to pass to sfdisk's -C argument. If None the -C argument is not passed. :param should_align_boot_part: Whether to align the boot partition too. + :param part_table Type of partition table, either 'mbr' or 'gpt'. """ + label = 'msdos' + if part_table == 'gpt': + label = part_table + if media.is_block_device: # Overwrite any existing partition tables with a fresh one. proc = cmd_runner.run( - ['parted', '-s', media.path, 'mklabel', 'msdos'], as_root=True) + ['parted', '-s', media.path, 'mklabel', label], as_root=True) proc.wait() - wait_partition_to_settle(media) + wait_partition_to_settle(media, part_table) - sfdisk_cmd = board_config.get_sfdisk_cmd( - should_align_boot_part=should_align_boot_part) + if part_table == 'gpt': + sgdisk_cmd = board_config.get_sgdisk_cmd( + should_align_boot_part=should_align_boot_part) + + run_sgdisk_commands(sgdisk_cmd, media.path) + else: # default partition table to mbr + sfdisk_cmd = board_config.get_sfdisk_cmd( + should_align_boot_part=should_align_boot_part) - run_sfdisk_commands(sfdisk_cmd, heads, sectors, cylinders, media.path) + run_sfdisk_commands(sfdisk_cmd, heads, sectors, cylinders, media.path) # Sync and sleep to wait for the partition to settle. cmd_runner.run(['sync']).wait() - wait_partition_to_settle(media) + wait_partition_to_settle(media, part_table) -def wait_partition_to_settle(media): +def wait_partition_to_settle(media, part_table): """Sleep in a loop to wait partition to settle :param media: A setup_partitions.Media object to partition. @@ -599,9 +619,12 @@ def wait_partition_to_settle(media): logger.info("Sleeping for %s second(s) to wait " "for the partition to settle" % tts) time.sleep(tts) - proc = cmd_runner.run( - ['sfdisk', '-l', media.path], - as_root=True, stdout=open('/dev/null', 'w')) + + args = ['sfdisk', '-l', media.path] + if part_table == 'gpt': + args = ['sgdisk', '-L', media.path] + proc = cmd_runner.run(args, as_root=True, + stdout=open('/dev/null', 'w')) proc.wait() return 0 except cmd_runner.SubcommandNonZeroReturnValue: diff --git a/linaro_image_tools/media_create/tests/test_media_create.py b/linaro_image_tools/media_create/tests/test_media_create.py index 937d942..0d21ad0 100644 --- a/linaro_image_tools/media_create/tests/test_media_create.py +++ b/linaro_image_tools/media_create/tests/test_media_create.py @@ -3001,7 +3001,7 @@ class TestCreatePartitions(TestCaseWithFixtures): media = Media(tmpfile) media.is_block_device = True - self.assertEqual(0, wait_partition_to_settle(media)) + self.assertEqual(0, wait_partition_to_settle(media, 'mbr')) def test_wait_partitions_to_settle_raises_SubcommandNonZeroReturnValue( self): @@ -3018,8 +3018,7 @@ class TestCreatePartitions(TestCaseWithFixtures): media.is_block_device = True self.assertRaises(cmd_runner.SubcommandNonZeroReturnValue, - wait_partition_to_settle, - media) + wait_partition_to_settle, media, 'mbr') class TestPartitionSetup(TestCaseWithFixtures): |