diff options
| author | Tom Rini <[email protected]> | 2026-01-16 09:18:34 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-01-16 09:53:57 -0600 |
| commit | 1da640cc46ad84efb57bb45e02dd6c40265b5488 (patch) | |
| tree | 29a54e26b2a6e032b9ba5b99a7207a52acd69025 | |
| parent | 03893b263a64b06ef06769b5526918fabd7a774f (diff) | |
| parent | 0efe1d9502a022d5d5c39c73340dd0b7b3f9cbe5 (diff) | |
Merge tag 'u-boot-dfu-20260116' of https://source.denx.de/u-boot/custodians/u-boot-dfu
u-boot-dfu-20260116
CI: https://source.denx.de/u-boot/custodians/u-boot-dfu/-/pipelines/29018
Android:
* Fix missing dependency for BOOTMETH_ANDROID
* Add bootconfig support
* Add 'get ramdisk' command to abootimg
DFU:
* Improve error handling in dfu_fill_entity()
USB Gadget:
* ci_udc: Ensure ci_ep->desc is valid before using it
* ci_udc: Add additional debug prints
| -rw-r--r-- | boot/Kconfig | 1 | ||||
| -rw-r--r-- | boot/bootmeth_android.c | 4 | ||||
| -rw-r--r-- | boot/image-android.c | 272 | ||||
| -rw-r--r-- | cmd/abootimg.c | 55 | ||||
| -rw-r--r-- | drivers/dfu/dfu.c | 52 | ||||
| -rw-r--r-- | drivers/usb/gadget/ci_udc.c | 57 | ||||
| -rw-r--r-- | test/py/tests/test_android/test_abootimg.py | 89 |
7 files changed, 436 insertions, 94 deletions
diff --git a/boot/Kconfig b/boot/Kconfig index 676a42a6ed4..b090f3c4c11 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -550,6 +550,7 @@ config BOOTMETH_ANDROID depends on X86 || ARM || SANDBOX depends on CMDLINE select ANDROID_BOOT_IMAGE + select CMD_ABOOTIMG select CMD_BCB imply CMD_FASTBOOT imply FASTBOOT if !NET_LWIP diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c index 1374551dbeb..1d70e8d5c05 100644 --- a/boot/bootmeth_android.c +++ b/boot/bootmeth_android.c @@ -252,8 +252,10 @@ static int android_read_bootflow(struct udevice *dev, struct bootflow *bflow) priv->boot_mode = ANDROID_BOOT_MODE_NORMAL; bflow->os_name = strdup("Android"); } - if (!bflow->os_name) + if (!bflow->os_name) { + free(priv); return log_msg_ret("os", -ENOMEM); + } if (priv->boot_mode == ANDROID_BOOT_MODE_BOOTLOADER) { /* Clear BCB */ diff --git a/boot/image-android.c b/boot/image-android.c index ea47869a64c..fb26290d40c 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -57,6 +57,46 @@ static ulong add_trailer(ulong bootconfig_start_addr, ulong bootconfig_size) return BOOTCONFIG_TRAILER_SIZE; } +/* + * Add a string of boot config parameters to memory appended by the trailer. + * NOTE: This function expects bootconfig_start_addr to be already mapped. + * It works directly with the mapped pointer, not a physical address. + */ +static long add_bootconfig_parameters(char *params, long params_len, + ulong bootconfig_start_addr, u32 bootconfig_size) +{ + long applied_bytes = 0; + long new_size = 0; + ulong end; + + if (!params || !bootconfig_start_addr) + return -EINVAL; + + if (params_len == 0) + return 0; + + end = bootconfig_start_addr + bootconfig_size; + + if (is_trailer_present(end)) { + end -= BOOTCONFIG_TRAILER_SIZE; + applied_bytes -= BOOTCONFIG_TRAILER_SIZE; + memcpy(&new_size, (void *)end, BOOTCONFIG_SIZE_SIZE); + } else { + /* + * When no trailer is present, the bootconfig_size includes the actual content. + * We should write new parameters right after the existing content. + */ + end = bootconfig_start_addr + bootconfig_size; + new_size = bootconfig_size; + } + + memcpy((void *)end, params, params_len); + applied_bytes += params_len; + applied_bytes += add_trailer(bootconfig_start_addr, + bootconfig_size + applied_bytes); + return applied_bytes; +} + __weak ulong get_avendor_bootimg_addr(void) { return -1; @@ -74,7 +114,7 @@ static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 * The header takes a full page, the remaining components are aligned * on page boundary. */ - end = (ulong)hdr; + end = map_to_sysmem(hdr); end += ANDR_GKI_PAGE_SIZE; data->kernel_ptr = end; data->kernel_size = hdr->kernel_size; @@ -87,7 +127,7 @@ static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 if (hdr->header_version > 3) end += ALIGN(hdr->signature_size, ANDR_GKI_PAGE_SIZE); - data->boot_img_total_size = end - (ulong)hdr; + data->boot_img_total_size = end - map_to_sysmem(hdr); } static void android_vendor_boot_image_v3_v4_parse_hdr(const struct andr_vnd_boot_img_hdr @@ -106,7 +146,7 @@ static void android_vendor_boot_image_v3_v4_parse_hdr(const struct andr_vnd_boot data->ramdisk_addr = hdr->ramdisk_addr; data->dtb_load_addr = hdr->dtb_addr; data->bootconfig_size = hdr->bootconfig_size; - end = (ulong)hdr; + end = map_to_sysmem(hdr); if (hdr->header_version > 3) end += ALIGN(ANDR_VENDOR_BOOT_V4_SIZE, hdr->page_size); @@ -127,12 +167,16 @@ static void android_vendor_boot_image_v3_v4_parse_hdr(const struct andr_vnd_boot end += ALIGN(hdr->vendor_ramdisk_table_size, hdr->page_size); data->bootconfig_addr = end; if (hdr->bootconfig_size) { - data->bootconfig_size += add_trailer(data->bootconfig_addr, + void *bootconfig_ptr = map_sysmem(data->bootconfig_addr, + data->bootconfig_size + + BOOTCONFIG_TRAILER_SIZE); + data->bootconfig_size += add_trailer((ulong)bootconfig_ptr, data->bootconfig_size); + unmap_sysmem(bootconfig_ptr); data->ramdisk_size += data->bootconfig_size; } end += ALIGN(data->bootconfig_size, hdr->page_size); - data->vendor_boot_img_total_size = end - (ulong)hdr; + data->vendor_boot_img_total_size = end - map_to_sysmem(hdr); } static void android_boot_image_v0_v1_v2_parse_hdr(const struct andr_boot_img_hdr_v0 *hdr, @@ -147,7 +191,7 @@ static void android_boot_image_v0_v1_v2_parse_hdr(const struct andr_boot_img_hdr data->header_version = hdr->header_version; data->dtb_load_addr = hdr->dtb_addr; - end = (ulong)hdr; + end = map_to_sysmem(hdr); /* * The header takes a full page, the remaining components are aligned @@ -180,7 +224,7 @@ static void android_boot_image_v0_v1_v2_parse_hdr(const struct andr_boot_img_hdr end += ALIGN(hdr->dtb_size, hdr->page_size); } - data->boot_img_total_size = end - (ulong)hdr; + data->boot_img_total_size = end - map_to_sysmem(hdr); } bool android_image_get_bootimg_size(const void *hdr, u32 *boot_img_size) @@ -231,31 +275,42 @@ bool android_image_get_vendor_bootimg_size(const void *hdr, u32 *vendor_boot_img bool android_image_get_data(const void *boot_hdr, const void *vendor_boot_hdr, struct andr_image_data *data) { + const struct andr_boot_img_hdr_v0 *bhdr; + const struct andr_vnd_boot_img_hdr *vhdr; + if (!boot_hdr || !data) { printf("boot_hdr or data params can't be NULL\n"); return false; } - if (!is_android_boot_image_header(boot_hdr)) { + bhdr = map_sysmem((ulong)boot_hdr, sizeof(*bhdr)); + if (!is_android_boot_image_header(bhdr)) { printf("Incorrect boot image header\n"); + unmap_sysmem(bhdr); return false; } - if (((struct andr_boot_img_hdr_v0 *)boot_hdr)->header_version > 2) { + if (bhdr->header_version > 2) { if (!vendor_boot_hdr) { printf("For boot header v3+ vendor boot image has to be provided\n"); + unmap_sysmem(bhdr); return false; } - if (!is_android_vendor_boot_image_header(vendor_boot_hdr)) { + vhdr = map_sysmem((ulong)vendor_boot_hdr, sizeof(*vhdr)); + if (!is_android_vendor_boot_image_header(vhdr)) { printf("Incorrect vendor boot image header\n"); + unmap_sysmem(vhdr); + unmap_sysmem(bhdr); return false; } - android_boot_image_v3_v4_parse_hdr(boot_hdr, data); - android_vendor_boot_image_v3_v4_parse_hdr(vendor_boot_hdr, data); + android_boot_image_v3_v4_parse_hdr((const struct andr_boot_img_hdr_v3 *)bhdr, data); + android_vendor_boot_image_v3_v4_parse_hdr(vhdr, data); + unmap_sysmem(vhdr); } else { - android_boot_image_v0_v1_v2_parse_hdr(boot_hdr, data); + android_boot_image_v0_v1_v2_parse_hdr(bhdr, data); } + unmap_sysmem(bhdr); return true; } @@ -450,6 +505,166 @@ ulong android_image_get_kcomp(const void *hdr, return image_decomp_type(p, sizeof(u32)); } +/** + * android_boot_append_bootconfig() - Append bootconfig parameters to ramdisk + * @img_data: Pointer to Android image data + * @params: Pointer to boot config parameters to append + * @params_len: Length of boot config parameters + * @ramdisk_dest: Destination address for the merged ramdisk + * + * This function copies the vendor ramdisk, boot ramdisk, and bootconfig to + * the destination. It then appends the provided bootconfig parameters. + * + * Return: Bytes added to the bootconfig on success, negative on error. + */ +static long android_boot_append_bootconfig(const struct andr_image_data *img_data, + char *params, long params_len, + void *ramdisk_dest) +{ + void *vendor_ramdisk_src; + void *boot_ramdisk_src; + void *bootconfig_src; + long bytes_added = 0; + + /* Map sources */ + vendor_ramdisk_src = map_sysmem(img_data->vendor_ramdisk_ptr, + img_data->vendor_ramdisk_size); + boot_ramdisk_src = map_sysmem(img_data->ramdisk_ptr, + img_data->boot_ramdisk_size); + + /* Copy Vendor Ramdisk */ + memcpy(ramdisk_dest, vendor_ramdisk_src, img_data->vendor_ramdisk_size); + + /* Copy Boot Ramdisk */ + memcpy((char *)ramdisk_dest + img_data->vendor_ramdisk_size, + boot_ramdisk_src, img_data->boot_ramdisk_size); + + /* Copy Bootconfig and Append Params */ + if (img_data->bootconfig_size) { + bootconfig_src = map_sysmem(img_data->bootconfig_addr, + img_data->bootconfig_size); + memcpy((char *)ramdisk_dest + img_data->vendor_ramdisk_size + + img_data->boot_ramdisk_size, + bootconfig_src, img_data->bootconfig_size); + unmap_sysmem(bootconfig_src); + + if (params && params_len > 1) { + void *bootconfig_ptr = (char *)ramdisk_dest + + img_data->vendor_ramdisk_size + + img_data->boot_ramdisk_size; + bytes_added = add_bootconfig_parameters(params, params_len, + (ulong)bootconfig_ptr, + img_data->bootconfig_size); + } + } + + unmap_sysmem(boot_ramdisk_src); + unmap_sysmem(vendor_ramdisk_src); + + if (bytes_added < 0) + return bytes_added; + + return bytes_added; +} + +/** + * android_image_set_bootconfig() - Extract androidboot.* args and append to bootconfig + * @hdr: Pointer to boot image header + * @vendor_boot_img: Pointer to vendor boot image header + * @ramdisk_addr: Destination address for the merged ramdisk + * + * Return: Size of the bootconfig section (including new params) on success, negative on error. + */ +static long android_image_set_bootconfig(const void *hdr, + const void *vendor_boot_img, + ulong ramdisk_addr) +{ + const char *bootargs = env_get("bootargs"); + char *params = NULL; + char *new_bootargs = NULL; + long params_len = 0; + struct andr_image_data img_data; + long ret; + size_t len; + const char *src; + char *bc_dst; + char *args_dst; + ulong total_size; + void *ramdisk_dest; + + if (!android_image_get_data(hdr, vendor_boot_img, &img_data)) + return -EINVAL; + + /* Extract androidboot.* parameters from bootargs */ + if (bootargs && img_data.bootconfig_size) { + len = strlen(bootargs); + src = bootargs; + + params = malloc(len + 1); + new_bootargs = malloc(len + 1); + if (!params || !new_bootargs) { + free(params); + free(new_bootargs); + printf("Error: malloc failed\n"); + return -ENOMEM; + } + + bc_dst = params; + args_dst = new_bootargs; + + /* Extract androidboot.* and build new bootargs in one pass */ + while (*src) { + /* Skip leading spaces */ + while (*src == ' ') + src++; + if (!*src) + break; + + /* Check if this param starts with androidboot. */ + if (strncmp(src, "androidboot.", 12) == 0) { + /* Copy to bootconfig (add newline if not first) */ + if (bc_dst != params) + *bc_dst++ = '\n'; + while (*src && *src != ' ') + *bc_dst++ = *src++; + } else { + /* Copy to new bootargs (add space if not first) */ + if (args_dst != new_bootargs) + *args_dst++ = ' '; + while (*src && *src != ' ') + *args_dst++ = *src++; + } + } + + *bc_dst++ = '\n'; /* Final newline for bootconfig */ + *bc_dst = '\0'; + *args_dst = '\0'; + params_len = bc_dst - params; + + /* Update bootargs if we extracted any androidboot params */ + if (params_len > 1) + env_set("bootargs", new_bootargs); + } + + /* Calculate total size for mapping */ + total_size = img_data.ramdisk_size + img_data.bootconfig_size; + if (params_len > 1) + total_size += params_len + BOOTCONFIG_TRAILER_SIZE; + + /* Map Dest */ + ramdisk_dest = map_sysmem(ramdisk_addr, total_size); + + /* Copy data */ + ret = android_boot_append_bootconfig(&img_data, params, params_len, + ramdisk_dest); + + unmap_sysmem(ramdisk_dest); + free(params); + free(new_bootargs); + + return ret; +} + int android_image_get_ramdisk(const void *hdr, const void *vendor_boot_img, ulong *rd_data, ulong *rd_len) { @@ -481,17 +696,9 @@ int android_image_get_ramdisk(const void *hdr, const void *vendor_boot_img, ramdisk_ptr = img_data.ramdisk_addr; } *rd_data = ramdisk_ptr; - memcpy((void *)(ramdisk_ptr), (void *)img_data.vendor_ramdisk_ptr, - img_data.vendor_ramdisk_size); - ramdisk_ptr += img_data.vendor_ramdisk_size; - memcpy((void *)(ramdisk_ptr), (void *)img_data.ramdisk_ptr, - img_data.boot_ramdisk_size); - ramdisk_ptr += img_data.boot_ramdisk_size; - if (img_data.bootconfig_size) { - memcpy((void *) - (ramdisk_ptr), (void *)img_data.bootconfig_addr, - img_data.bootconfig_size); - } + if (img_data.header_version > 3) + img_data.ramdisk_size += + android_image_set_bootconfig(hdr, vendor_boot_img, ramdisk_ptr); } else { /* Ramdisk can be used in-place, use current ptr */ if (img_data.ramdisk_addr == 0 || @@ -684,21 +891,14 @@ bool android_image_get_dtb_by_index(ulong hdr_addr, ulong vendor_boot_img, u32 index, ulong *addr, u32 *size) { struct andr_image_data img_data; - const struct andr_boot_img_hdr_v0 *hdr; - const struct andr_vnd_boot_img_hdr *vhdr = NULL; + const void *vendor_boot_hdr = NULL; - hdr = map_sysmem(hdr_addr, sizeof(*hdr)); if (vendor_boot_img != -1) - vhdr = map_sysmem(vendor_boot_img, sizeof(*vhdr)); - if (!android_image_get_data(hdr, vhdr, &img_data)) { - if (vendor_boot_img != -1) - unmap_sysmem(vhdr); - unmap_sysmem(hdr); + vendor_boot_hdr = (const void *)vendor_boot_img; + + if (!android_image_get_data((const void *)hdr_addr, vendor_boot_hdr, + &img_data)) return false; - } - if (vendor_boot_img != -1) - unmap_sysmem(vhdr); - unmap_sysmem(hdr); ulong dtb_img_addr; /* address of DTB part in boot image */ u32 dtb_img_size; /* size of DTB payload in boot image */ diff --git a/cmd/abootimg.c b/cmd/abootimg.c index 6fb52153786..eae3e643b60 100644 --- a/cmd/abootimg.c +++ b/cmd/abootimg.c @@ -92,26 +92,18 @@ static int abootimg_get_recovery_dtbo(int argc, char *const argv[]) static int abootimg_get_dtb_load_addr(int argc, char *const argv[]) { + struct andr_image_data img_data = {0}; + const void *vendor_boot_hdr = NULL; + if (argc > 1) return CMD_RET_USAGE; - struct andr_image_data img_data = {0}; - const struct andr_boot_img_hdr_v0 *hdr; - const struct andr_vnd_boot_img_hdr *vhdr = NULL; - hdr = map_sysmem(abootimg_addr(), sizeof(*hdr)); if (get_avendor_bootimg_addr() != -1) - vhdr = map_sysmem(get_avendor_bootimg_addr(), sizeof(*vhdr)); + vendor_boot_hdr = (const void *)get_avendor_bootimg_addr(); - if (!android_image_get_data(hdr, vhdr, &img_data)) { - if (get_avendor_bootimg_addr() != -1) - unmap_sysmem(vhdr); - unmap_sysmem(hdr); + if (!android_image_get_data((const void *)abootimg_addr(), + vendor_boot_hdr, &img_data)) return CMD_RET_FAILURE; - } - - if (get_avendor_bootimg_addr() != -1) - unmap_sysmem(vhdr); - unmap_sysmem(hdr); if (img_data.header_version < 2) { printf("Error: header_version must be >= 2 for this\n"); @@ -230,6 +222,33 @@ static int do_abootimg_addr(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_SUCCESS; } +static int abootimg_get_ramdisk(int argc, char *const argv[]) +{ + ulong rd_data, rd_len; + + if (argc > 2) + return CMD_RET_USAGE; + + /* + * Call android_image_get_ramdisk with UNMAPPED addresses + * The function will do its own mapping internally as needed + */ + if (android_image_get_ramdisk((void *)abootimg_addr(), + (void *)get_avendor_bootimg_addr(), + &rd_data, &rd_len)) + return CMD_RET_FAILURE; + + if (argc == 0) { + printf("%lx\n", rd_data); + } else { + env_set_hex(argv[0], rd_data); + if (argc == 2) + env_set_hex(argv[1], rd_len); + } + + return CMD_RET_SUCCESS; +} + static int do_abootimg_get(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -249,6 +268,8 @@ static int do_abootimg_get(struct cmd_tbl *cmdtp, int flag, int argc, return abootimg_get_dtb_load_addr(argc, argv); else if (!strcmp(param, "dtb")) return abootimg_get_dtb(argc, argv); + else if (!strcmp(param, "ramdisk")) + return abootimg_get_ramdisk(argc, argv); return CMD_RET_USAGE; } @@ -315,5 +336,9 @@ U_BOOT_CMD( " - get address and size (hex) of DT blob in the image by index\n" " <num>: index number of desired DT blob in DTB area\n" " [addr_var]: variable name to contain DT blob address\n" - " [size_var]: variable name to contain DT blob size" + " [size_var]: variable name to contain DT blob size\n" + "abootimg get ramdisk [addr_var [size_var]]\n" + " - get address and size (hex) of ramdisk in the image\n" + " [addr_var]: variable name to contain ramdisk address\n" + " [size_var]: variable name to contain ramdisk size" ); diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index eefdf44ec87..90d8b45ce8a 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -185,7 +185,7 @@ int dfu_init_env_entities(char *interface, char *devstr) ret = dfu_config_entities(env_bkp, interface, devstr); if (ret) { - pr_err("DFU entities configuration failed!\n"); + pr_err("DFU entities configuration failed: %d\n", ret); pr_err("(partition table does not match dfu_alt_info?)\n"); goto done; } @@ -518,7 +518,7 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, char *interface, char *devstr) { char *argv[DFU_MAX_ENTITY_ARGS]; - int argc; + int argc, ret; char *st; debug("%s: %s interface: %s dev: %s\n", __func__, s, interface, devstr); @@ -547,30 +547,37 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, /* Specific for mmc device */ if (strcmp(interface, "mmc") == 0) { - if (dfu_fill_entity_mmc(dfu, devstr, argv, argc)) - return -1; + ret = dfu_fill_entity_mmc(dfu, devstr, argv, argc); + if (ret) + return ret; } else if (strcmp(interface, "mtd") == 0) { - if (dfu_fill_entity_mtd(dfu, devstr, argv, argc)) - return -1; + ret = dfu_fill_entity_mtd(dfu, devstr, argv, argc); + if (ret) + return ret; } else if (strcmp(interface, "nand") == 0) { - if (dfu_fill_entity_nand(dfu, devstr, argv, argc)) - return -1; + ret = dfu_fill_entity_nand(dfu, devstr, argv, argc); + if (ret) + return ret; } else if (strcmp(interface, "ram") == 0) { - if (dfu_fill_entity_ram(dfu, devstr, argv, argc)) - return -1; + ret = dfu_fill_entity_ram(dfu, devstr, argv, argc); + if (ret) + return ret; } else if (strcmp(interface, "sf") == 0) { - if (dfu_fill_entity_sf(dfu, devstr, argv, argc)) - return -1; + ret = dfu_fill_entity_sf(dfu, devstr, argv, argc); + if (ret) + return ret; } else if (strcmp(interface, "virt") == 0) { - if (dfu_fill_entity_virt(dfu, devstr, argv, argc)) - return -1; + ret = dfu_fill_entity_virt(dfu, devstr, argv, argc); + if (ret) + return ret; } else if (strcmp(interface, "scsi") == 0) { - if (dfu_fill_entity_scsi(dfu, devstr, argv, argc)) - return -1; + ret = dfu_fill_entity_scsi(dfu, devstr, argv, argc); + if (ret) + return ret; } else { printf("%s: Device %s not (yet) supported!\n", __func__, interface); - return -1; + return -EOPNOTSUPP; } dfu_get_buf(dfu); @@ -624,12 +631,12 @@ int dfu_alt_add(struct dfu_entity *dfu, char *interface, char *devstr, char *s) int ret; if (alt_num_cnt >= dfu_alt_num) - return -1; + return -EINVAL; p_dfu = &dfu[alt_num_cnt]; ret = dfu_fill_entity(p_dfu, s, alt_num_cnt, interface, devstr); if (ret) - return -1; + return ret; list_add_tail(&p_dfu->list, &dfu_list); alt_num_cnt++; @@ -645,16 +652,15 @@ int dfu_config_entities(char *env, char *interface, char *devstr) ret = dfu_alt_init(dfu_find_alt_num(env), &dfu); if (ret) - return -1; + return ret; for (i = 0; i < dfu_alt_num; i++) { s = strsep(&env, ";"); s = skip_spaces(s); ret = dfu_alt_add(dfu, interface, devstr, s); - if (ret) { + if (ret) /* We will free "dfu" in dfu_free_entities() */ - return -1; - } + return ret; } return 0; diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c index 4bff75da759..046bb335ecb 100644 --- a/drivers/usb/gadget/ci_udc.c +++ b/drivers/usb/gadget/ci_udc.c @@ -273,8 +273,10 @@ ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags) if (ci_ep->desc) num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - if (num == 0 && controller.ep0_req) + if (num == 0 && controller.ep0_req) { + DBG("%s: already got controller.ep0_req = %p\n", __func__, controller.ep0_req); return &controller.ep0_req->req; + } ci_req = calloc(1, sizeof(*ci_req)); if (!ci_req) @@ -296,6 +298,8 @@ static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *req) if (ci_ep->desc) num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + else + DBG("%s: no endpoint %p descriptor\n", __func__, ci_ep); if (num == 0) { if (!controller.ep0_req) @@ -308,6 +312,27 @@ static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *req) free(ci_req); } +static void request_complete(struct usb_ep *ep, struct ci_req *req, int status) +{ + if (req->req.status == -EINPROGRESS) + req->req.status = status; + + DBG("%s: req %p complete: status %d, actual %u\n", + ep->name, req, req->req.status, req->req.actual); + + req->req.complete(ep, &req->req); +} + +static void request_complete_list(struct usb_ep *ep, struct list_head *list, int status) +{ + struct ci_req *req, *tmp_req; + + list_for_each_entry_safe(req, tmp_req, list, queue) { + list_del_init(&req->queue); + request_complete(ep, req, status); + } +} + static void ep_enable(int num, int in, int maxpacket) { struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; @@ -335,6 +360,12 @@ static int ci_ep_enable(struct usb_ep *ep, int num, in; num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; in = (desc->bEndpointAddress & USB_DIR_IN) != 0; + + if (ci_ep->desc) { + DBG("%s: endpoint num %d in %d already enabled\n", __func__, num, in); + return -EBUSY; + } + ci_ep->desc = desc; ep->desc = desc; @@ -385,19 +416,32 @@ static int ep_disable(int num, int in) static int ci_ep_disable(struct usb_ep *ep) { struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); + LIST_HEAD(req_list); int num, in, err; + if (!ci_ep->desc) { + DBG("%s: attempt to disable a not enabled yet endpoint\n", __func__); + err = -EBUSY; + goto nodesc; + } + num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; + list_splice_init(&ci_ep->queue, &req_list); + request_complete_list(ep, &req_list, -ESHUTDOWN); + err = ep_disable(num, in); if (err) return err; ci_ep->desc = NULL; + err = 0; + +nodesc: ep->desc = NULL; ci_ep->req_primed = false; - return 0; + return err; } static int ci_bounce(struct ci_req *ci_req, int in) @@ -584,8 +628,10 @@ static int ci_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) break; } - if (&ci_req->req != _req) + if (&ci_req->req != _req) { + DBG("%s: ci_req not found in the queue\n", __func__); return -EINVAL; + } list_del_init(&ci_req->queue); @@ -606,6 +652,11 @@ static int ci_ep_queue(struct usb_ep *ep, int in, ret; int __maybe_unused num; + if (!ci_ep->desc) { + DBG("%s: ci_ep->desc == NULL, nothing to do!\n", __func__); + return -EINVAL; + } + num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; diff --git a/test/py/tests/test_android/test_abootimg.py b/test/py/tests/test_android/test_abootimg.py index daa87643e93..ff54a8318a1 100644 --- a/test/py/tests/test_android/test_abootimg.py +++ b/test/py/tests/test_android/test_abootimg.py @@ -62,22 +62,24 @@ b7762ffff07d345446c1281805e8a0868d81e117a45e111c0d8dc101b253 d4a9820881a70f3873f35352731892f3730b124b32937252a96bb9119ae5 463a5546f82c1f05a360148c8251300a462e000085bf67f200200000""" -# boot img v4 hex dump -boot_img_hex = """1f8b080827b0cd630203626f6f742e696d6700edd8bd0d82601885d1d7c4 -58d8c808b88195bd098d8d246e40e42b083f1aa0717be99d003d277916b8 -e5bddc8a7b792d8e8788c896ce9b88d32ebe6c971e7ddd3543cae734cd01 -c0ffc84c0000b0766d1a87d4e5afeadd3dab7a6f10000000f84163d5d7cd -d43a000000000000000060c53e7544995700400000""" - -# vendor boot image v4 hex dump -vboot_img_hex = """1f8b0808baaecd63020376626f6f742e696d6700edd8310b824018c6f1b3 -222a08f41b3436b4280dcdd19c11d16ee9109d18d59042d047ec8b04cd0d -d19d5a4345534bf6ffc173ef29272f38e93b1d0ec67dd79d548462aa1cd2 -d5d20b0000f8438678f90c18d584b8a4bbb3a557991ecb2a0000f80d6b2f -f4179b656be5c532f2fc066f040000000080e23936af2755f62a3d918df1 -db2a7ab67f9ffdeb7df7cda3465ecb79c4ce7e5c577562bb9364b74449a5 -1e467e20c53c0a57de763193c1779b3b4fcd9d4ee27c6a0e00000000c0ff -309ffea7010000000040f1dc004129855400400000""" +# bootable boot image v4 hex dump (with DTBs) +boot_img_hex = """1f8b0808e2dd60690203626f6f745f6e65772e696d6700edd8ab0d836018 +40d14f900a0c8c5036e80a24180c24dde04f4034d04740b13d02d90920e7 +8c70e5adbbe6d9b74d5544441987c72dfe64010000009cd5342e9f71beff +d2367fd3900b0200000017b4a4f7f05a2703000000002e6c0765d9bd6000 +300000""" + +# bootable vendor boot image v4 hex dump (with DTBs + bootconfig) +vboot_img_hex = """1f8b0808e2dd6069020376656e646f725f626f6f745f6e65772e696d6700 +eddb316bc24014c0f14b2dd20a425c3b393a48c1d0c1a54be9aca588fbc5 +0b3434e9c979d04628f811fd22426787d2bbc43a68e9d4a5f1ff83f7de25 +5c787053f220d3d1fde3dd783c39174ee86255e68e4f0000e00405e2e835 +e0e142886db9fae8f89c95dbaa7ac5890100f02f1899ab74f1dc9dcb22d3 +52b538110000000000ea67ddfedcb8f2ee6228aa317ecf859fed7fcffefd +fae68747835d6dec42bc0df6d74d1fc5a0bfac6e89331797b9564926663a +9f4b9bc659f2b7cda383e6517f19fdd61c0000000080d3111e7c4f030000 +000080fa912fcae854c55adbeb2769d4ab34c9ad4d16963f010000000000 +a88d2fb468951800500000""" # Expected response for "abootimg dtb_dump" command dtb_dump_resp="""## DTB area contents (concat format): @@ -282,3 +284,58 @@ def test_abootimgv4(abootimgv4_disk_image_vboot, abootimgv4_disk_image_boot, ubm ubman.run_command('fdt get value v / model') response = ubman.run_command('env print v') assert response == 'v=x2' + [email protected]('sandbox') [email protected]('android_boot_image') [email protected]('cmd_abootimg') [email protected]('xxd') [email protected]('gunzip') +def test_abootimg_bootconfig(abootimgv4_disk_image_vboot, + abootimgv4_disk_image_boot, + ubman): + """Test bootconfig handling with boot image v4. + + Verifies that androidboot.* parameters from bootargs are appended to the + bootconfig section in vendor_boot image in memory, and that non-androidboot + parameters remain in bootargs. + """ + + # Setup addresses + ram_base = utils.find_ram_base(ubman) + ramdisk_addr_r = ram_base + 0x4000000 + ubman.run_command('setenv ramdisk_addr_r 0x%x' % ramdisk_addr_r) + ubman.run_command('setenv loadaddr 0x%x' % loadaddr) + ubman.run_command('setenv vloadaddr 0x%x' % vloadaddr) + + # Set bootargs with androidboot.* parameters + ubman.run_command('setenv bootargs "androidboot.serialno=ABC123 androidboot.mode=recovery console=ttyS0"') + + # Load images + ubman.run_command('host load hostfs - 0x%x %s' % (vloadaddr, + abootimgv4_disk_image_vboot.path)) + ubman.run_command('host load hostfs - 0x%x %s' % (loadaddr, + abootimgv4_disk_image_boot.path)) + ubman.run_command('abootimg addr 0x%x 0x%x' % (loadaddr, vloadaddr)) + + # Extract ramdisk (triggers bootconfig append) + ubman.run_command('abootimg get ramdisk ramdisk_addr ramdisk_size') + + # Get ramdisk address + response = ubman.run_command('env print ramdisk_addr') + ramdisk_start = int(response.split('=')[1], 16) + + # Verify androidboot.* parameters were removed from bootargs + response = ubman.run_command('env print bootargs') + assert 'androidboot.' not in response + assert 'console=ttyS0' in response + + # Get ramdisk size and verify BOOTCONFIG magic at the end + response = ubman.run_command('env print ramdisk_size') + ramdisk_size = int(response.split('=')[1], 16) + + # Dump the end of the ramdisk where BOOTCONFIG trailer should be + # The trailer is at the end, so dump the last 48 bytes + response = ubman.run_command('md.b 0x%x 48' % (ramdisk_start + ramdisk_size - 48)) + + # Verify BOOTCONFIG magic is present + assert 'BOOTCONFIG' in response |
