aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSemen Protsenko <semen.protsenko@linaro.org>2014-06-04 11:11:04 +0100
committerFathi Boudra <fathi.boudra@linaro.org>2014-06-14 12:21:00 +0000
commit0c28539742ead845da3c08bae63be5af9a71d0d7 (patch)
treec034a8cd2d482a679763ea6245a36270cbdb389c
parent23231928b4e6d1d6df985defe9de4ee0e0f04db1 (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>
-rwxr-xr-xlinaro-media-create5
-rw-r--r--linaro_image_tools/media_create/__init__.py3
-rw-r--r--linaro_image_tools/media_create/boards.py76
-rw-r--r--linaro_image_tools/media_create/partitions.py49
-rw-r--r--linaro_image_tools/media_create/tests/test_media_create.py5
5 files changed, 103 insertions, 35 deletions
diff --git a/linaro-media-create b/linaro-media-create
index ba3984f..727c8ff 100755
--- a/linaro-media-create
+++ b/linaro-media-create
@@ -94,7 +94,7 @@ def cleanup_tempdir():
def ensure_required_commands(args):
"""Ensure we have the commands that we know are going to be used."""
required_commands = [
- 'mkfs.vfat', 'sfdisk', 'mkimage', 'parted', 'gpg', 'sha1sum']
+ 'mkfs.vfat', 'sfdisk', 'mkimage', 'parted', 'gpg', 'sha1sum', 'sgdisk']
if not is_arm_host():
required_commands.append('qemu-arm-static')
if args.rootfs in ['btrfs', 'ext2', 'ext3', 'ext4']:
@@ -241,7 +241,8 @@ if __name__ == '__main__':
boot_partition, root_partition = setup_partitions(
board_config, media, args.image_size, args.boot_label, args.rfs_label,
args.rootfs, args.should_create_partitions, args.should_format_bootfs,
- args.should_format_rootfs, args.should_align_boot_part)
+ args.should_format_rootfs, args.should_align_boot_part,
+ args.part_table)
uuid = get_uuid(root_partition)
# In case we're only extracting the kernel packages, avoid
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):