diff mbox series

[v2,3/4] image-commands: support Chromium OS image-type creation

Message ID 20210117030707.1251501-4-computersforpeace@gmail.com
State Superseded, archived
Delegated to: Paul Spooren
Headers show
Series Add support for Chromium OS and Google WiFi | expand

Commit Message

Brian Norris Jan. 17, 2021, 3:07 a.m. UTC
See the previous patches, which implemented the cros-vbutil
verified-boot payload-packing tool, and extended ptgen for the CrOS
kernel partition type. With these, it's now possible to package kernel +
rootfs to make disk images that can boot a Chrome OS-based system (e.g.,
Chromebooks, or even a few AP models).

gen_image_vboot.sh borrows a bit of structure from gen_image_generic.sh,
but I didn't feel it fit well to try and add new flags to the latter,
given the difference in its FAT kernel packaging and our raw kernel
partition packing.

Signed-off-by: Brian Norris <computersforpeace@gmail.com>
---
 include/image-commands.mk                     | 18 ++++++++++
 .../base-files/files/lib/upgrade/common.sh    |  4 ++-
 scripts/gen_image_vboot.sh                    | 36 +++++++++++++++++++
 3 files changed, 57 insertions(+), 1 deletion(-)
 create mode 100755 scripts/gen_image_vboot.sh

Comments

Paul Spooren Jan. 17, 2021, 10:43 a.m. UTC | #1
On Sat Jan 16, 2021 at 5:07 PM HST, Brian Norris wrote:
> See the previous patches, which implemented the cros-vbutil
> verified-boot payload-packing tool, and extended ptgen for the CrOS
> kernel partition type. With these, it's now possible to package kernel +
> rootfs to make disk images that can boot a Chrome OS-based system (e.g.,
> Chromebooks, or even a few AP models).
>
> gen_image_vboot.sh borrows a bit of structure from gen_image_generic.sh,
> but I didn't feel it fit well to try and add new flags to the latter,
> given the difference in its FAT kernel packaging and our raw kernel
> partition packing.
>
> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
> ---
> include/image-commands.mk | 18 ++++++++++
> .../base-files/files/lib/upgrade/common.sh | 4 ++-
> scripts/gen_image_vboot.sh | 36 +++++++++++++++++++
> 3 files changed, 57 insertions(+), 1 deletion(-)
> create mode 100755 scripts/gen_image_vboot.sh
>
> diff --git a/include/image-commands.mk b/include/image-commands.mk
> index 979eafb15734..f02d8e79fce6 100644
> --- a/include/image-commands.mk
> +++ b/include/image-commands.mk
> @@ -172,6 +172,24 @@ define Build/fit
> @mv $@.new $@
> endef
>  
> +define Build/cros-image
> + $(SCRIPT_DIR)/gen_image_vboot.sh \
> + $@ \
> + $(CONFIG_TARGET_KERNEL_PARTSIZE) \

You're passing the kernel size twice here which the script expects
<size> <image>. Am I missing something?

> + $(CONFIG_TARGET_KERNEL_PARTSIZE) $(IMAGE_KERNEL) \
> + $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS)
> +endef
> +
> +# NB: Chrome OS bootloaders replace the '%U' in command lines with the
> UUID of
> +# the kernel partition it chooses to boot from. This gives a flexible
> way to
> +# consistently build and sign kernels that always use the subsequent
> +# (PARTNROFF=1) partition as their rootfs.
> +define Build/cros-vboot
> + $(STAGING_DIR_HOST)/bin/cros-vbutil \
> + -k $@ -c "root=PARTUUID=%U/PARTNROFF=1" -o $@.new
> + @mv $@.new $@
> +endef
> +
> define Build/gzip
> gzip -f -9n -c $@ $(1) > $@.new
> @mv $@.new $@
> diff --git a/package/base-files/files/lib/upgrade/common.sh
> b/package/base-files/files/lib/upgrade/common.sh
> index c28bae48a15c..a2ee8d1675a6 100644
> --- a/package/base-files/files/lib/upgrade/common.sh
> +++ b/package/base-files/files/lib/upgrade/common.sh
> @@ -178,9 +178,11 @@ export_bootdevice() {
> fi
> done
> ;;
> + PARTUUID=????????-????-????-????-??????????01/PARTNROFF=1 | \
> PARTUUID=????????-????-????-????-??????????02)
> uuid="${rootpart#PARTUUID=}"
> - uuid="${uuid%02}00"
> + uuid="${uuid%/PARTNROFF=1}"
> + uuid="${uuid%0?}00"
> for disk in $(find /dev -type b); do
> set -- $(dd if=$disk bs=1 skip=568 count=16 2>/dev/null | hexdump -v -e
> '8/1 "%02x "" "2/1 "%02x""-"6/1 "%02x"')
> if [ "$4$3$2$1-$6$5-$8$7-$9" = "$uuid" ]; then
> diff --git a/scripts/gen_image_vboot.sh b/scripts/gen_image_vboot.sh
> new file mode 100755
> index 000000000000..ae267ba3fbb9
> --- /dev/null
> +++ b/scripts/gen_image_vboot.sh
> @@ -0,0 +1,36 @@
> +#!/usr/bin/env bash
> +# Copyright (C) 2021 OpenWrt.org
> +set -e -x
> +[ $# == 6 ] || {
> + echo "SYNTAX: $0 <file> <bootpart size> <kernel size> <kernel image>
> <rootfs size> <rootfs image>"
> + exit 1
> +}
> +
> +OUTPUT="$1"
> +BOOTPARTSIZE="$2"
> +KERNELSIZE="$3"
> +KERNELIMAGE="$4"
> +ROOTFSSIZE="$5"
> +ROOTFSIMAGE="$6"
> +
> +rm -f "${OUTPUT}"
> +
> +head=16
> +sect=63
> +
> +# create partition table
> +set $(ptgen -o "${OUTPUT}" -h $head -s $sect -g -p ${BOOTPARTSIZE}m -T
> cros_kernel -p ${KERNELSIZE}m -p ${ROOTFSSIZE}m)
> +
> +BOOTOFFSET="$(($1 / 512))"
> +BOOTSIZE="$2"
> +KERNELOFFSET="$(($3 / 512))"
> +KERNELSIZE="$4"
> +ROOTFSOFFSET="$(($5 / 512))"
> +ROOTFSSIZE="$(($6 / 512))"
> +
> +mkfs.fat -n boot -C "${OUTPUT}.boot" -S 512 "$((BOOTSIZE / 1024))"
> +
> +dd if="${OUTPUT}.boot" of="${OUTPUT}" bs=512 seek="${BOOTOFFSET}"
> conv=notrunc
> +rm -f "${OUTPUT}.boot"
> +dd if="${KERNELIMAGE}" of="${OUTPUT}" bs=512 seek="${KERNELOFFSET}"
> conv=notrunc
> +dd if="${ROOTFSIMAGE}" of="${OUTPUT}" bs=512 seek="${ROOTFSOFFSET}"
> conv=notrunc
> --
> 2.29.2
>
>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel
Brian Norris Jan. 17, 2021, 5:20 p.m. UTC | #2
Hi Paul,

On Sun, Jan 17, 2021 at 2:43 AM Paul Spooren <mail@aparcar.org> wrote:
> On Sat Jan 16, 2021 at 5:07 PM HST, Brian Norris wrote:
> > See the previous patches, which implemented the cros-vbutil
> > verified-boot payload-packing tool, and extended ptgen for the CrOS
> > kernel partition type. With these, it's now possible to package kernel +
> > rootfs to make disk images that can boot a Chrome OS-based system (e.g.,
> > Chromebooks, or even a few AP models).
> >
> > gen_image_vboot.sh borrows a bit of structure from gen_image_generic.sh,
> > but I didn't feel it fit well to try and add new flags to the latter,
> > given the difference in its FAT kernel packaging and our raw kernel
> > partition packing.
> >
> > Signed-off-by: Brian Norris <computersforpeace@gmail.com>
> > ---
> > include/image-commands.mk | 18 ++++++++++
> > .../base-files/files/lib/upgrade/common.sh | 4 ++-
> > scripts/gen_image_vboot.sh | 36 +++++++++++++++++++
> > 3 files changed, 57 insertions(+), 1 deletion(-)
> > create mode 100755 scripts/gen_image_vboot.sh
> >
> > diff --git a/include/image-commands.mk b/include/image-commands.mk
> > index 979eafb15734..f02d8e79fce6 100644
> > --- a/include/image-commands.mk
> > +++ b/include/image-commands.mk
> > @@ -172,6 +172,24 @@ define Build/fit
> > @mv $@.new $@
> > endef
> >
> > +define Build/cros-image
> > + $(SCRIPT_DIR)/gen_image_vboot.sh \
> > + $@ \
> > + $(CONFIG_TARGET_KERNEL_PARTSIZE) \
>
> You're passing the kernel size twice here which the script expects
> <size> <image>. Am I missing something?

From the error/help text:

    echo "SYNTAX: $0 <file> <bootpart size> <kernel size> <kernel
image> <rootfs size> <rootfs image>"

It's a bit awkward, but for the first partition, it's only asking for
a <size>. I haven't fully fleshed it out yet, but this first partition
is a spare FAT partition, for use in sysupgrade. I believe other
systems reuse the kernel partition (which tends to be either FAT or
ext4), but because Chrome OS systems use a signed blob (and not a
proper filesystem) for their kernel partitions, I needed to create an
extra partition, with no special data in it.

Also, I don't really have a separate Kconfig option for defining the
FAT partition size -- I just reused the kernel partition size.

I'm open to suggestions on this, but the current code is written as
intended. I'm not very familiar with OpenWRT image-construction best
practices (e.g., adding more Kconfig parameters?).

Thanks,
Brian
Paul Spooren Jan. 17, 2021, 6:10 p.m. UTC | #3
On So, Jan 17, 2021 at 09:20, Brian Norris 
<computersforpeace@gmail.com> wrote:
> Hi Paul,
> 
> On Sun, Jan 17, 2021 at 2:43 AM Paul Spooren <mail@aparcar.org> wrote:
>>  On Sat Jan 16, 2021 at 5:07 PM HST, Brian Norris wrote:
>>  > See the previous patches, which implemented the cros-vbutil
>>  > verified-boot payload-packing tool, and extended ptgen for the 
>> CrOS
>>  > kernel partition type. With these, it's now possible to package 
>> kernel +
>>  > rootfs to make disk images that can boot a Chrome OS-based system 
>> (e.g.,
>>  > Chromebooks, or even a few AP models).
>>  >
>>  > gen_image_vboot.sh borrows a bit of structure from 
>> gen_image_generic.sh,
>>  > but I didn't feel it fit well to try and add new flags to the 
>> latter,
>>  > given the difference in its FAT kernel packaging and our raw 
>> kernel
>>  > partition packing.
>>  >
>>  > Signed-off-by: Brian Norris <computersforpeace@gmail.com>
>>  > ---
>>  > include/image-commands.mk | 18 ++++++++++
>>  > .../base-files/files/lib/upgrade/common.sh | 4 ++-
>>  > scripts/gen_image_vboot.sh | 36 +++++++++++++++++++
>>  > 3 files changed, 57 insertions(+), 1 deletion(-)
>>  > create mode 100755 scripts/gen_image_vboot.sh
>>  >
>>  > diff --git a/include/image-commands.mk b/include/image-commands.mk
>>  > index 979eafb15734..f02d8e79fce6 100644
>>  > --- a/include/image-commands.mk
>>  > +++ b/include/image-commands.mk
>>  > @@ -172,6 +172,24 @@ define Build/fit
>>  > @mv $@.new $@
>>  > endef
>>  >
>>  > +define Build/cros-image
>>  > + $(SCRIPT_DIR)/gen_image_vboot.sh \
>>  > + $@ \
>>  > + $(CONFIG_TARGET_KERNEL_PARTSIZE) \
>> 
>>  You're passing the kernel size twice here which the script expects
>>  <size> <image>. Am I missing something?
> 
> From the error/help text:
> 
>     echo "SYNTAX: $0 <file> <bootpart size> <kernel size> <kernel
> image> <rootfs size> <rootfs image>"
> 
> It's a bit awkward, but for the first partition, it's only asking for
> a <size>. I haven't fully fleshed it out yet, but this first partition
> is a spare FAT partition, for use in sysupgrade. I believe other
> systems reuse the kernel partition (which tends to be either FAT or
> ext4), but because Chrome OS systems use a signed blob (and not a
> proper filesystem) for their kernel partitions, I needed to create an
> extra partition, with no special data in it.
> 
> Also, I don't really have a separate Kconfig option for defining the
> FAT partition size -- I just reused the kernel partition size.
> 
> I'm open to suggestions on this, but the current code is written as
> intended. I'm not very familiar with OpenWRT image-construction best
> practices (e.g., adding more Kconfig parameters?).

Sorry for the confusion, within a git rebase the file wasn't updated 
and lacked that parameter, causing error message on execution. It works 
fine now.

I have no idea for a better name, if you suspect other devices could 
use this functionality as well that use other sizes we should design it 
more flexible.

> Thanks,
> Brian
diff mbox series

Patch

diff --git a/include/image-commands.mk b/include/image-commands.mk
index 979eafb15734..f02d8e79fce6 100644
--- a/include/image-commands.mk
+++ b/include/image-commands.mk
@@ -172,6 +172,24 @@  define Build/fit
 	@mv $@.new $@
 endef
 
+define Build/cros-image
+	$(SCRIPT_DIR)/gen_image_vboot.sh \
+		  $@ \
+		  $(CONFIG_TARGET_KERNEL_PARTSIZE) \
+		  $(CONFIG_TARGET_KERNEL_PARTSIZE) $(IMAGE_KERNEL) \
+		  $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS)
+endef
+
+# NB: Chrome OS bootloaders replace the '%U' in command lines with the UUID of
+# the kernel partition it chooses to boot from. This gives a flexible way to
+# consistently build and sign kernels that always use the subsequent
+# (PARTNROFF=1) partition as their rootfs.
+define Build/cros-vboot
+	$(STAGING_DIR_HOST)/bin/cros-vbutil \
+		-k $@ -c "root=PARTUUID=%U/PARTNROFF=1" -o $@.new
+	@mv $@.new $@
+endef
+
 define Build/gzip
 	gzip -f -9n -c $@ $(1) > $@.new
 	@mv $@.new $@
diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh
index c28bae48a15c..a2ee8d1675a6 100644
--- a/package/base-files/files/lib/upgrade/common.sh
+++ b/package/base-files/files/lib/upgrade/common.sh
@@ -178,9 +178,11 @@  export_bootdevice() {
 					fi
 				done
 			;;
+			PARTUUID=????????-????-????-????-??????????01/PARTNROFF=1 | \
 			PARTUUID=????????-????-????-????-??????????02)
 				uuid="${rootpart#PARTUUID=}"
-				uuid="${uuid%02}00"
+				uuid="${uuid%/PARTNROFF=1}"
+				uuid="${uuid%0?}00"
 				for disk in $(find /dev -type b); do
 					set -- $(dd if=$disk bs=1 skip=568 count=16 2>/dev/null | hexdump -v -e '8/1 "%02x "" "2/1 "%02x""-"6/1 "%02x"')
 					if [ "$4$3$2$1-$6$5-$8$7-$9" = "$uuid" ]; then
diff --git a/scripts/gen_image_vboot.sh b/scripts/gen_image_vboot.sh
new file mode 100755
index 000000000000..ae267ba3fbb9
--- /dev/null
+++ b/scripts/gen_image_vboot.sh
@@ -0,0 +1,36 @@ 
+#!/usr/bin/env bash
+# Copyright (C) 2021 OpenWrt.org
+set -e -x
+[ $# == 6 ] || {
+    echo "SYNTAX: $0 <file> <bootpart size> <kernel size> <kernel image> <rootfs size> <rootfs image>"
+    exit 1
+}
+
+OUTPUT="$1"
+BOOTPARTSIZE="$2"
+KERNELSIZE="$3"
+KERNELIMAGE="$4"
+ROOTFSSIZE="$5"
+ROOTFSIMAGE="$6"
+
+rm -f "${OUTPUT}"
+
+head=16
+sect=63
+
+# create partition table
+set $(ptgen -o "${OUTPUT}" -h $head -s $sect -g -p ${BOOTPARTSIZE}m -T cros_kernel -p ${KERNELSIZE}m -p ${ROOTFSSIZE}m)
+
+BOOTOFFSET="$(($1 / 512))"
+BOOTSIZE="$2"
+KERNELOFFSET="$(($3 / 512))"
+KERNELSIZE="$4"
+ROOTFSOFFSET="$(($5 / 512))"
+ROOTFSSIZE="$(($6 / 512))"
+
+mkfs.fat -n boot -C "${OUTPUT}.boot" -S 512 "$((BOOTSIZE / 1024))"
+
+dd if="${OUTPUT}.boot" of="${OUTPUT}" bs=512 seek="${BOOTOFFSET}" conv=notrunc
+rm -f "${OUTPUT}.boot"
+dd if="${KERNELIMAGE}" of="${OUTPUT}" bs=512 seek="${KERNELOFFSET}" conv=notrunc
+dd if="${ROOTFSIMAGE}" of="${OUTPUT}" bs=512 seek="${ROOTFSOFFSET}" conv=notrunc