From 3aefd4332700d1fb8b97f3a734cb8959c366c6f9 Mon Sep 17 00:00:00 2001 From: Safae Ouajih <souajih@baylibre.com> Date: Thu, 11 Aug 2022 15:30:38 +0200 Subject: [PATCH] android boot image header v4 bootconfig support This adds support for bootconfig feature. Signed-off-by: Safae Ouajih <souajih@baylibre.com> --- boot/image-android.c | 15 +++++- include/android_image.h | 3 +- include/xbc.h | 1 + lib/Kconfig | 12 +++++ lib/Makefile | 1 + lib/libxbc/Makefile | 1 + lib/libxbc/libxbc.c | 112 ++++++++++++++++++++++++++++++++++++++++ lib/libxbc/libxbc.h | 54 +++++++++++++++++++ 8 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 include/xbc.h create mode 100644 lib/libxbc/Makefile create mode 100644 lib/libxbc/libxbc.c create mode 100644 lib/libxbc/libxbc.h diff --git a/boot/image-android.c b/boot/image-android.c index 39cdce11abe..67ee8d16582 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -13,6 +13,7 @@ #include <asm/unaligned.h> #include <mapmem.h> #include <linux/libfdt.h> +#include <xbc.h> #define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000 @@ -115,6 +116,7 @@ void android_vendor_boot_image_v3_v4_get_end(const struct andr_vendor_boot_img_h data->image_name = hdr->name; data->kernel_load_addr = hdr->kernel_addr; data->ramdisk_load_addr = hdr->ramdisk_addr; + data->bootconfig_size = hdr->bootconfig_size; end = (ulong)hdr; end += hdr->page_size; if (hdr->vendor_ramdisk_size) { @@ -129,7 +131,14 @@ void android_vendor_boot_image_v3_v4_get_end(const struct andr_vendor_boot_img_h end += ALIGN(hdr->dtb_size, hdr->page_size); end += ALIGN(hdr->vendor_ramdisk_table_size, hdr->page_size); - end += ALIGN(hdr->bootconfig_size, hdr->page_size); + + data->bootconfig_addr = end; + if (hdr->bootconfig_size) { + data->bootconfig_size += addBootConfigTrailer(data->bootconfig_addr, data->bootconfig_size); + data->ramdisk_size += data->bootconfig_size; + } + + end += ALIGN(data->bootconfig_size, hdr->page_size); data->boot_img_total_size = end - (ulong)hdr; } @@ -320,6 +329,10 @@ int android_image_get_ramdisk(const void *boot_img, const void *vendor_boot_img, ulong ramdisk_ptr = img_data.ramdisk_ptr; memcpy((void *)(ramdisk_ptr), (void *)img_data.vendor_ramdisk_ptr, img_data.vendor_ramdisk_size); memcpy((void *)(ramdisk_ptr + img_data.vendor_ramdisk_size), (void*)img_data.ramdisk_ptr, img_data.boot_ramdisk_size); + if (img_data.bootconfig_size) { + memcpy((void *)(ramdisk_ptr + img_data.vendor_ramdisk_size + img_data.boot_ramdisk_size), + (void*)img_data.bootconfig_addr, img_data.bootconfig_size); + } } printf("RAM disk load addr 0x%08lx size %u KiB\n", diff --git a/include/android_image.h b/include/android_image.h index 529680076bd..96541bf32a4 100644 --- a/include/android_image.h +++ b/include/android_image.h @@ -332,7 +332,8 @@ struct andr_image_data { uint32_t dtb_size; ulong recovery_dtbo_ptr; uint32_t recovery_dtbo_size; - + ulong bootconfig_addr; + ulong bootconfig_size; const char *kcmdline; const char *kcmdline_extra; const char *image_name; diff --git a/include/xbc.h b/include/xbc.h new file mode 100644 index 00000000000..725e65ff6ad --- /dev/null +++ b/include/xbc.h @@ -0,0 +1 @@ +#include <../lib/libxbc/libxbc.h> diff --git a/lib/Kconfig b/lib/Kconfig index 3c6fa99b1a6..6406e713c27 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -386,6 +386,18 @@ config LIBAVB endmenu +menu "Boot Configuration" +config XBC + bool "Boot Configuration support" + depends on ANDROID_BOOT_IMAGE + default n + help + This enables support of Boot Configuration which can be used + to pass boot configuration parameters to user space. These + parameters will show up in /proc/bootconfig similar to the kernel + parameters that show up in /proc/cmdline +endmenu + menu "Hashing Support" config BLAKE2 diff --git a/lib/Makefile b/lib/Makefile index 11b03d1cbec..15fb58f8bb6 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -85,6 +85,7 @@ obj-$(CONFIG_$(SPL_)LZ4) += lz4_wrapper.o obj-$(CONFIG_$(SPL_)LIB_RATIONAL) += rational.o obj-$(CONFIG_LIBAVB) += libavb/ +obj-$(CONFIG_XBC) += libxbc/ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ obj-$(CONFIG_$(SPL_TPL_)OF_REAL) += fdtdec_common.o fdtdec.o diff --git a/lib/libxbc/Makefile b/lib/libxbc/Makefile new file mode 100644 index 00000000000..05da3f6d578 --- /dev/null +++ b/lib/libxbc/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_XBC) += libxbc.o diff --git a/lib/libxbc/libxbc.c b/lib/libxbc/libxbc.c new file mode 100644 index 00000000000..129bffc7c62 --- /dev/null +++ b/lib/libxbc/libxbc.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "libxbc.h" +#define BOOTCONFIG_MAGIC "#BOOTCONFIG\n" +#define BOOTCONFIG_MAGIC_SIZE 12 +#define BOOTCONFIG_SIZE_SIZE 4 +#define BOOTCONFIG_CHECKSUM_SIZE 4 +#define BOOTCONFIG_TRAILER_SIZE BOOTCONFIG_MAGIC_SIZE + \ + BOOTCONFIG_SIZE_SIZE + \ + BOOTCONFIG_CHECKSUM_SIZE + +/* + * Simple checksum for a buffer. + * + * @param addr pointer to the start of the buffer. + * @param size size of the buffer in bytes. + * @return check sum result. + */ +static uint32_t checksum(const unsigned char* const buffer, uint32_t size) { + uint32_t sum = 0; + for (uint32_t i = 0; i < size; i++) { + sum += buffer[i]; + } + return sum; +} + +/* + * Check if the bootconfig trailer is present within the bootconfig section. + * + * @param bootconfig_end_addr address of the end of the bootconfig section. If + * the trailer is present, it will be directly preceding this address. + * @return true if the trailer is present, false if not. + */ +static bool isTrailerPresent(uint64_t bootconfig_end_addr) { + return !strncmp((char*)(bootconfig_end_addr - BOOTCONFIG_MAGIC_SIZE), + BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_SIZE); +} + +/* + * Add a string of boot config parameters to memory appended by the trailer. + */ +int32_t addBootConfigParameters(char* params, uint32_t params_size, + uint64_t bootconfig_start_addr, uint32_t bootconfig_size) { + if (!params || !bootconfig_start_addr) { + return -1; + } + if (params_size == 0) { + return 0; + } + int32_t applied_bytes = 0; + int32_t new_size = 0; + uint64_t end = bootconfig_start_addr + bootconfig_size; + if (isTrailerPresent(end)) { + end -= BOOTCONFIG_TRAILER_SIZE; + applied_bytes -= BOOTCONFIG_TRAILER_SIZE; + memcpy(&new_size, (void *)end, BOOTCONFIG_SIZE_SIZE); + } else { + new_size = bootconfig_size; + } + // params + memcpy((void*)end, params, params_size); + applied_bytes += params_size; + applied_bytes += addBootConfigTrailer(bootconfig_start_addr, + bootconfig_size + applied_bytes); + return applied_bytes; +} + +/* + * Add boot config trailer. + */ + +int32_t addBootConfigTrailer(uint64_t bootconfig_start_addr, + uint32_t bootconfig_size) { + if (!bootconfig_start_addr) { + return -1; + } + + if (bootconfig_size == 0) { + return 0; + } + + uint64_t end = bootconfig_start_addr + bootconfig_size; + if (isTrailerPresent(end)) { + return 0; + } + + // size + memcpy((void *)(end), &bootconfig_size, BOOTCONFIG_SIZE_SIZE); + + // checksum + uint32_t sum = checksum((unsigned char*)bootconfig_start_addr, bootconfig_size); + memcpy((void *)(end + BOOTCONFIG_SIZE_SIZE), &sum, BOOTCONFIG_CHECKSUM_SIZE); + + // magic + memcpy((void *)(end + BOOTCONFIG_SIZE_SIZE + BOOTCONFIG_CHECKSUM_SIZE), + BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_SIZE); + + return BOOTCONFIG_TRAILER_SIZE; +} diff --git a/lib/libxbc/libxbc.h b/lib/libxbc/libxbc.h new file mode 100644 index 00000000000..0b6ba496090 --- /dev/null +++ b/lib/libxbc/libxbc.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LIBXBC_H_ +#define LIBXBC_H_ + +#include <common.h> +/* + * Add a string of boot config parameters to memory appended by the trailer. + * This memory needs to be immediately following the end of the ramdisks. + * The new boot config trailer will be written to the end of the entire + * parameter section(previous + new). The trailer contains a 4 byte size of the + * parameters, followed by a 4 byte checksum of the parameters, followed by a 12 + * byte magic string. + * + * @param params pointer to string of boot config parameters + * @param params_size size of params string in bytes + * @param bootconfig_start_addr address that the boot config section is starting + * at in memory. + * @param bootconfig_size size of the current bootconfig section in bytes. + * @return number of bytes added to the boot config section. -1 for error. + */ +int addBootConfigParameters(char *params, uint32_t params_size, + uint64_t bootconfig_start_addr, + uint32_t bootconfig_size); +/* + * Add the boot config trailer to the end of the boot config parameter section. + * This can be used after the vendor bootconfig section has been placed into + * memory if there are no additional parameters that need to be added. + * The new boot config trailer will be written to the end of the entire + * parameter section at (bootconfig_start_addr + bootconfig_size). + * The trailer contains a 4 byte size of the parameters, followed by a 4 byte + * checksum of the parameters, followed by a 12 byte magic string. + * + * @param bootconfig_start_addr address that the boot config section is starting + * at in memory. + * @param bootconfig_size size of the current bootconfig section in bytes. + * @return number of bytes added to the boot config section. -1 for error. + */ +int addBootConfigTrailer(uint64_t bootconfig_start_addr, + uint32_t bootconfig_size); +#endif /* LIBXBC_H_ */ -- GitLab