Support ChromeOS partition table and kernel partition (MR 2163)
Stock bootloader on these devices boots kernel (it is intended to boot kernel, but i place secondary bootloader there) from special ChromeOS kernel partition on special GPT which is created with cgpt utility. This MR adds initial support for it introducing new deviceinfo options: - cgpt_kpart - path to file to be flashed to ChromeOS partition; - cgpt_kpart_start - offset from the start in sectors; - cgpt_kpart_size - partition size in sectors. For example: deviceinfo_cgpt_kpart="/usr/share/u-boot/google-peach-pit/u-boot-dtb.img.kpart" deviceinfo_cgpt_kpart_start="8192" deviceinfo_cgpt_kpart_size="32768" cgpt requires start and size values of partition, so these values are calculated for each partition. Reserved size and on-device installer are not yet supported. Reference: https://archlinuxarm.org/platforms/armv7/samsung/samsung-chromebook
This commit is contained in:
parent
2363732645
commit
7b2ffc3e5f
|
@ -715,6 +715,9 @@ deviceinfo_attributes = [
|
||||||
"partition_type",
|
"partition_type",
|
||||||
"root_filesystem",
|
"root_filesystem",
|
||||||
"flash_kernel_on_update",
|
"flash_kernel_on_update",
|
||||||
|
"cgpt_kpart",
|
||||||
|
"cgpt_kpart_start",
|
||||||
|
"cgpt_kpart_size",
|
||||||
|
|
||||||
# weston
|
# weston
|
||||||
"weston_pixman_type",
|
"weston_pixman_type",
|
||||||
|
|
|
@ -260,6 +260,10 @@ def install(args):
|
||||||
if args.filesystem:
|
if args.filesystem:
|
||||||
raise ValueError("--on-device-installer cannot be combined with"
|
raise ValueError("--on-device-installer cannot be combined with"
|
||||||
" --filesystem")
|
" --filesystem")
|
||||||
|
|
||||||
|
if args.deviceinfo["cgpt_kpart"]:
|
||||||
|
raise ValueError("--on-device-installer cannot be used with"
|
||||||
|
" ChromeOS devices")
|
||||||
else:
|
else:
|
||||||
if args.ondev_cp:
|
if args.ondev_cp:
|
||||||
raise ValueError("--cp can only be combined with --ondev")
|
raise ValueError("--cp can only be combined with --ondev")
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
from pmb.install._install import install
|
from pmb.install._install import install
|
||||||
from pmb.install._install import get_kernel_package
|
from pmb.install._install import get_kernel_package
|
||||||
from pmb.install.partition import partition
|
from pmb.install.partition import partition
|
||||||
|
from pmb.install.partition import partition_cgpt
|
||||||
from pmb.install.format import format
|
from pmb.install.format import format
|
||||||
from pmb.install.format import get_root_filesystem
|
from pmb.install.format import get_root_filesystem
|
||||||
from pmb.install.partition import partitions_mount
|
from pmb.install.partition import partitions_mount
|
||||||
|
|
|
@ -553,6 +553,22 @@ def embed_firmware(args, suffix):
|
||||||
"bs=" + str(step), "seek=" + str(offset)])
|
"bs=" + str(step), "seek=" + str(offset)])
|
||||||
|
|
||||||
|
|
||||||
|
def write_cgpt_kpart(args, layout, suffix):
|
||||||
|
"""
|
||||||
|
Write the kernel to the ChromeOS kernel partition.
|
||||||
|
|
||||||
|
:param layout: partition layout from get_partition_layout()
|
||||||
|
:param suffix: of the chroot, which holds the image file to be flashed
|
||||||
|
"""
|
||||||
|
if not args.deviceinfo["cgpt_kpart"]:
|
||||||
|
return
|
||||||
|
|
||||||
|
device_rootfs = mount_device_rootfs(args, suffix)
|
||||||
|
filename = f"{device_rootfs}{args.deviceinfo['cgpt_kpart']}"
|
||||||
|
pmb.chroot.root(
|
||||||
|
args, ["dd", f"if={filename}", f"of=/dev/installp{layout['kernel']}"])
|
||||||
|
|
||||||
|
|
||||||
def sanity_check_sdcard(args):
|
def sanity_check_sdcard(args):
|
||||||
device = args.sdcard
|
device = args.sdcard
|
||||||
device_name = os.path.basename(device)
|
device_name = os.path.basename(device)
|
||||||
|
@ -607,17 +623,25 @@ def sanity_check_ondev_version(args):
|
||||||
f" / in the binary packages has version {ver_pkg}.")
|
f" / in the binary packages has version {ver_pkg}.")
|
||||||
|
|
||||||
|
|
||||||
def get_partition_layout(reserve):
|
def get_partition_layout(reserve, kernel):
|
||||||
"""
|
"""
|
||||||
:param reserve: create an empty partition between root and boot (pma#463)
|
:param reserve: create an empty partition between root and boot (pma#463)
|
||||||
|
:param kernel: create a separate kernel partition before all other
|
||||||
|
partitions, e.g. for the ChromeOS devices with cgpt
|
||||||
:returns: the partition layout, e.g. without reserve and kernel:
|
:returns: the partition layout, e.g. without reserve and kernel:
|
||||||
{"boot": 1, "reserve": None, "root": 2}
|
{"kernel": None, "boot": 1, "reserve": None, "root": 2}
|
||||||
"""
|
"""
|
||||||
ret = {}
|
ret = {}
|
||||||
|
ret["kernel"] = None
|
||||||
ret["boot"] = 1
|
ret["boot"] = 1
|
||||||
ret["reserve"] = None
|
ret["reserve"] = None
|
||||||
ret["root"] = 2
|
ret["root"] = 2
|
||||||
|
|
||||||
|
if kernel:
|
||||||
|
ret["kernel"] = 1
|
||||||
|
ret["boot"] += 1
|
||||||
|
ret["root"] += 1
|
||||||
|
|
||||||
if reserve:
|
if reserve:
|
||||||
ret["reserve"] = ret["root"]
|
ret["reserve"] = ret["root"]
|
||||||
ret["root"] += 1
|
ret["root"] += 1
|
||||||
|
@ -642,12 +666,16 @@ def install_system_image(args, size_reserve, suffix, step, steps,
|
||||||
logging.info(f"*** ({step}/{steps}) PREPARE INSTALL BLOCKDEVICE ***")
|
logging.info(f"*** ({step}/{steps}) PREPARE INSTALL BLOCKDEVICE ***")
|
||||||
pmb.chroot.shutdown(args, True)
|
pmb.chroot.shutdown(args, True)
|
||||||
(size_boot, size_root) = get_subpartitions_size(args, suffix)
|
(size_boot, size_root) = get_subpartitions_size(args, suffix)
|
||||||
layout = get_partition_layout(size_reserve)
|
layout = get_partition_layout(size_reserve, args.deviceinfo["cgpt_kpart"])
|
||||||
if not args.rsync:
|
if not args.rsync:
|
||||||
pmb.install.blockdevice.create(args, size_boot, size_root,
|
pmb.install.blockdevice.create(args, size_boot, size_root,
|
||||||
size_reserve, split, sdcard)
|
size_reserve, split, sdcard)
|
||||||
if not split:
|
if not split:
|
||||||
pmb.install.partition(args, layout, size_boot, size_reserve)
|
if args.deviceinfo["cgpt_kpart"]:
|
||||||
|
pmb.install.partition_cgpt(
|
||||||
|
args, layout, size_boot, size_reserve)
|
||||||
|
else:
|
||||||
|
pmb.install.partition(args, layout, size_boot, size_reserve)
|
||||||
if not split:
|
if not split:
|
||||||
pmb.install.partitions_mount(args, layout, sdcard)
|
pmb.install.partitions_mount(args, layout, sdcard)
|
||||||
|
|
||||||
|
@ -660,10 +688,11 @@ def install_system_image(args, size_reserve, suffix, step, steps,
|
||||||
configure_apk(args)
|
configure_apk(args)
|
||||||
copy_ssh_keys(args)
|
copy_ssh_keys(args)
|
||||||
|
|
||||||
# Don't try to embed firmware on split images since there's no
|
# Don't try to embed firmware and cgpt on split images since there's no
|
||||||
# place to put it and it will end up in /dev of the chroot instead
|
# place to put it and it will end up in /dev of the chroot instead
|
||||||
if not split:
|
if not split:
|
||||||
embed_firmware(args, suffix)
|
embed_firmware(args, suffix)
|
||||||
|
write_cgpt_kpart(args, layout, suffix)
|
||||||
|
|
||||||
if sdcard:
|
if sdcard:
|
||||||
logging.info("Unmounting SD card (this may take a while "
|
logging.info("Unmounting SD card (this may take a while "
|
||||||
|
|
|
@ -13,15 +13,15 @@ def install_fsprogs(args, filesystem):
|
||||||
pmb.chroot.apk.install(args, [fsprogs])
|
pmb.chroot.apk.install(args, [fsprogs])
|
||||||
|
|
||||||
|
|
||||||
def format_and_mount_boot(args, boot_label):
|
def format_and_mount_boot(args, device, boot_label):
|
||||||
"""
|
"""
|
||||||
|
:param device: boot partition on install block device (e.g. /dev/installp1)
|
||||||
:param boot_label: label of the root partition (e.g. "pmOS_boot")
|
:param boot_label: label of the root partition (e.g. "pmOS_boot")
|
||||||
|
|
||||||
When adjusting this function, make sure to also adjust
|
When adjusting this function, make sure to also adjust
|
||||||
ondev-prepare-internal-storage.sh in postmarketos-ondev.git!
|
ondev-prepare-internal-storage.sh in postmarketos-ondev.git!
|
||||||
"""
|
"""
|
||||||
mountpoint = "/mnt/install/boot"
|
mountpoint = "/mnt/install/boot"
|
||||||
device = "/dev/installp1"
|
|
||||||
filesystem = args.deviceinfo["boot_filesystem"] or "ext2"
|
filesystem = args.deviceinfo["boot_filesystem"] or "ext2"
|
||||||
install_fsprogs(args, filesystem)
|
install_fsprogs(args, filesystem)
|
||||||
logging.info(f"(native) format {device} (boot, {filesystem}), mount to"
|
logging.info(f"(native) format {device} (boot, {filesystem}), mount to"
|
||||||
|
@ -133,10 +133,11 @@ def format(args, layout, boot_label, root_label, sdcard):
|
||||||
:param sdcard: path to sdcard device (e.g. /dev/mmcblk0) or None
|
:param sdcard: path to sdcard device (e.g. /dev/mmcblk0) or None
|
||||||
"""
|
"""
|
||||||
root_dev = f"/dev/installp{layout['root']}"
|
root_dev = f"/dev/installp{layout['root']}"
|
||||||
|
boot_dev = f"/dev/installp{layout['boot']}"
|
||||||
|
|
||||||
if args.full_disk_encryption:
|
if args.full_disk_encryption:
|
||||||
format_luks_root(args, root_dev)
|
format_luks_root(args, root_dev)
|
||||||
root_dev = "/dev/mapper/pm_crypt"
|
root_dev = "/dev/mapper/pm_crypt"
|
||||||
|
|
||||||
format_and_mount_root(args, root_dev, root_label, sdcard)
|
format_and_mount_root(args, root_dev, root_label, sdcard)
|
||||||
format_and_mount_boot(args, boot_label)
|
format_and_mount_boot(args, boot_dev, boot_label)
|
||||||
|
|
|
@ -37,7 +37,12 @@ def partitions_mount(args, layout, sdcard):
|
||||||
prefix + " to be located at " + prefix +
|
prefix + " to be located at " + prefix +
|
||||||
"1 or " + prefix + "p1!")
|
"1 or " + prefix + "p1!")
|
||||||
|
|
||||||
for i in [1, layout["root"]]:
|
partitions = [layout["boot"], layout["root"]]
|
||||||
|
|
||||||
|
if layout["kernel"]:
|
||||||
|
partitions += [layout["kernel"]]
|
||||||
|
|
||||||
|
for i in partitions:
|
||||||
source = prefix + partition_prefix + str(i)
|
source = prefix + partition_prefix + str(i)
|
||||||
target = args.work + "/chroot_native/dev/installp" + str(i)
|
target = args.work + "/chroot_native/dev/installp" + str(i)
|
||||||
pmb.helpers.mount.bind_file(args, source, target)
|
pmb.helpers.mount.bind_file(args, source, target)
|
||||||
|
@ -91,3 +96,93 @@ def partition(args, layout, size_boot, size_reserve):
|
||||||
for command in commands:
|
for command in commands:
|
||||||
pmb.chroot.root(args, ["parted", "-s", "/dev/install"] +
|
pmb.chroot.root(args, ["parted", "-s", "/dev/install"] +
|
||||||
command, check=False)
|
command, check=False)
|
||||||
|
|
||||||
|
|
||||||
|
def partition_cgpt(args, layout, size_boot, size_reserve):
|
||||||
|
"""
|
||||||
|
This function does similar functionality to partition(), but this
|
||||||
|
one is for ChromeOS devices which use special GPT.
|
||||||
|
|
||||||
|
:param layout: partition layout from get_partition_layout()
|
||||||
|
:param size_boot: size of the boot partition in MiB
|
||||||
|
:param size_reserve: empty partition between root and boot in MiB (pma#463)
|
||||||
|
"""
|
||||||
|
|
||||||
|
pmb.chroot.root(args, ["apk", "add", "cgpt"])
|
||||||
|
|
||||||
|
cgpt = {
|
||||||
|
'kpart_start': args.deviceinfo["cgpt_kpart_start"],
|
||||||
|
'kpart_size': args.deviceinfo["cgpt_kpart_size"],
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert to MB and print info
|
||||||
|
mb_boot = f"{round(size_boot)}M"
|
||||||
|
mb_reserved = f"{round(size_reserve)}M"
|
||||||
|
logging.info(f"(native) partition /dev/install (boot: {mb_boot},"
|
||||||
|
f" reserved: {mb_reserved}, root: the rest)")
|
||||||
|
|
||||||
|
boot_part_start = str(int(cgpt['kpart_start']) + int(cgpt['kpart_size']))
|
||||||
|
|
||||||
|
# Convert to sectors
|
||||||
|
s_boot = str(int(size_boot * 1024 * 1024 / 512))
|
||||||
|
s_root_start = str(int(
|
||||||
|
int(boot_part_start) + int(s_boot) + size_reserve * 1024 * 1024 / 512
|
||||||
|
))
|
||||||
|
|
||||||
|
commands = [
|
||||||
|
["parted", "-s", "/dev/install", "mktable", "gpt"],
|
||||||
|
["cgpt", "create", "/dev/install"],
|
||||||
|
[
|
||||||
|
"cgpt", "add",
|
||||||
|
# pmOS_boot is second partition, the first will be ChromeOS kernel
|
||||||
|
# partition
|
||||||
|
"-i", str(layout["boot"]), # Partition number
|
||||||
|
"-t", "data",
|
||||||
|
"-b", boot_part_start,
|
||||||
|
"-s", s_boot,
|
||||||
|
"-l", "pmOS_boot",
|
||||||
|
"/dev/install"
|
||||||
|
],
|
||||||
|
# Mark this partition as bootable for u-boot
|
||||||
|
[
|
||||||
|
"parted",
|
||||||
|
"-s", "/dev/install",
|
||||||
|
"set", str(layout["boot"]),
|
||||||
|
"boot", "on"
|
||||||
|
],
|
||||||
|
# For some reason cgpt switches all flags to 0 after marking
|
||||||
|
# any partition as bootable, so create ChromeOS kernel partition
|
||||||
|
# only after pmOS_boot is created and marked as bootable
|
||||||
|
[
|
||||||
|
"cgpt", "add",
|
||||||
|
"-i", str(layout["kernel"]),
|
||||||
|
"-t", "kernel",
|
||||||
|
"-b", cgpt['kpart_start'],
|
||||||
|
"-s", cgpt['kpart_size'],
|
||||||
|
"-l", "Kernel",
|
||||||
|
"-S", "1", # Successful flag
|
||||||
|
"-T", "5", # Tries flag
|
||||||
|
"-P", "10", # Priority flag
|
||||||
|
"/dev/install"
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
dev_size = pmb.chroot.root(
|
||||||
|
args, ["blockdev", "--getsz", "/dev/install"], output_return=True)
|
||||||
|
root_size = str(int(dev_size) - int(s_root_start) - 1024)
|
||||||
|
|
||||||
|
commands += [
|
||||||
|
[
|
||||||
|
"cgpt", "add",
|
||||||
|
"-i", str(layout["root"]),
|
||||||
|
"-t", "data",
|
||||||
|
"-b", s_root_start,
|
||||||
|
"-s", root_size,
|
||||||
|
"-l", "pmOS_root",
|
||||||
|
"/dev/install"
|
||||||
|
],
|
||||||
|
["partx", "-a", "/dev/install"]
|
||||||
|
]
|
||||||
|
|
||||||
|
for command in commands:
|
||||||
|
pmb.chroot.root(args, command, check=False)
|
||||||
|
|
Loading…
Reference in New Issue