[gbl] Implement get_var in GBL EFI Fastboot protocol Delegate fastboot get_var queries from GBL to U-Boot environment variables via getenv(). TAG=agy CONV=236c2e4e-69e4-48b6-a8ea-8986bc68bb04 Change-Id: I8e1e68b24ae0479f9bc347e68e02b40077863feb Reviewed-on: https://turquoise-internal-review.googlesource.com/c/third_party/u-boot/+/1382091 Commit-Queue: Sergii Parubochyi <sergiip@google.com> Reviewed-by: David Pursell <dpursell@google.com> GitOrigin-RevId: 323089e5da1412ea9d3b0ab5e34a0d18b06999bc
diff --git a/common/Makefile b/common/Makefile index e6387b9..578b5ef 100644 --- a/common/Makefile +++ b/common/Makefile
@@ -372,7 +372,10 @@ CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null) -fuchsia_include = -I$(fuchsia_sdk)/zbi/include -I$(fuchsia_sdk)/zbi-format/include +fuchsia_include = -I$(fuchsia_sdk)/zbi/include -I$(fuchsia_sdk)/zbi-format/include -I$(fuchsia_sdk)/abr/include +CFLAGS_aboot.o += $(fuchsia_include) +CFLAGS_fb_mmc.o += $(fuchsia_include) +CFLAGS_fb_nand.o += $(fuchsia_include) CFLAGS_cmd_imgread.o += $(fuchsia_include) CFLAGS_image.o += $(fuchsia_include) CFLAGS_image-zircon.o += $(fuchsia_include)
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index ab3c1db..447e912 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c
@@ -561,7 +561,7 @@ // // On failure, this updates the fastboot TX buffer with a failure message and // returns NULL. -static const char *parse_fb_cmd_partition(char *cmd) +const char *parse_fb_cmd_partition(char *cmd) { strsep(&cmd, ":"); if (cmd == NULL) { @@ -659,7 +659,7 @@ } } -static const char* getvar_list[] = { +const char fastboot_getvar_list[][RESPONSE_LEN] = { "version-baseband", "version-bootloader", "version", "hw-revision", "max-download-size", "serialno", "product", "off-mode-charge", "variant", "battery-soc-ok", "battery-voltage", "partition-type:boot", "partition-size:boot", @@ -667,8 +667,9 @@ "partition-type:odm", "partition-size:odm", "partition-type:data", "partition-size:data", "erase-block-size", "logical-block-size", "secure", "unlocked", }; +const size_t fastboot_getvar_list_size = ARRAY_SIZE(fastboot_getvar_list); -static const char* getvar_list_dynamic[] = { +const char fastboot_getvar_list_dynamic[][RESPONSE_LEN] = { "hw-revision", "battery-voltage", "is-userspace", "is-logical:data", "is-logical:metadata", "is-logical:misc", "is-logical:super", "is-logical:boot", "is-logical:system", "is-logical:vendor", "is-logical:product", "is-logical:odm", @@ -679,8 +680,9 @@ "partition-size:boot", "partition-size:metadata", "partition-size:misc", "partition-size:super", "partition-size:data", "version", }; +const size_t fastboot_getvar_list_dynamic_size = ARRAY_SIZE(fastboot_getvar_list_dynamic); -static const char *getvar_list_ab[] = { +const char fastboot_getvar_list_ab[][RESPONSE_LEN] = { "current-slot", "has-slot:" GPT_DURABLE_BOOT_NAME, "has-slot:" GPT_FVM_NAME, @@ -716,12 +718,32 @@ "vx-locked", "vx-unlockable", }; +const size_t fastboot_getvar_list_ab_size = ARRAY_SIZE(fastboot_getvar_list_ab); + + +// Subset of fastboot_getvar_list_ab excluding GBL reserved values +const char fastboot_getvar_list_ab_gbl_limited[][RESPONSE_LEN] = { + "hw-revision", + "product", + "serialno", + "slot-suffixes", + "slot-unbootable-reason:a", + "slot-unbootable-reason:b", + "version", + "vx-locked", + "vx-unlockable", + // GBL would report own version via 'version-bootloader'. + // So need extra var to pass u-boot version. + "u-boot-version", +}; +const size_t fastboot_getvar_list_ab_gbl_limited_size = + ARRAY_SIZE(fastboot_getvar_list_ab_gbl_limited); extern ZirconBootOps zb_ops; // Returns slot info for the given slot string "a" or "b", or NULL on failure. // The returned struct is only valid until the next call to this function. -static AbrSlotInfo* get_slot_info(const char *suffix) +AbrSlotInfo* fastboot_get_slot_info(const char *suffix) { AbrSlotIndex slot_index; if (strcmp(suffix, "a") == 0) { @@ -746,7 +768,6 @@ char *cmd = req->buf; char cmdBuf[RESPONSE_LEN]; char* response = response_str; - char *s1; size_t chars_left; strcpy(response, "OKAY"); @@ -764,15 +785,15 @@ if (!strncmp(cmd, "all", 3)) { static int cmdIndex = 0; int getvar_num = 0; - if (has_boot_slot == 1 && strlen(getvar_list_ab[cmdIndex]) < 64) { - strcpy(cmd, getvar_list_ab[cmdIndex]); - getvar_num = (sizeof(getvar_list_ab) / sizeof(getvar_list_ab[0])); - } else if (dynamic_partition && strlen(getvar_list_dynamic[cmdIndex]) < 64) { - strcpy(cmd, getvar_list_dynamic[cmdIndex]);//only support no-arg cmd - getvar_num = (sizeof(getvar_list_dynamic) / sizeof(getvar_list_dynamic[0])); - } else if (strlen(getvar_list[cmdIndex]) < 64) { - strcpy(cmd, getvar_list[cmdIndex]);//only support no-arg cmd - getvar_num = (sizeof(getvar_list) / sizeof(getvar_list[0])); + if (has_boot_slot == 1 && cmdIndex < fastboot_getvar_list_ab_size) { + strcpy(cmd, fastboot_getvar_list_ab[cmdIndex]); + getvar_num = fastboot_getvar_list_ab_size; + } else if (dynamic_partition && cmdIndex < fastboot_getvar_list_dynamic_size) { + strcpy(cmd, fastboot_getvar_list_dynamic[cmdIndex]);//only support no-arg cmd + getvar_num = fastboot_getvar_list_dynamic_size; + } else if (cmdIndex < fastboot_getvar_list_size) { + strcpy(cmd, fastboot_getvar_list[cmdIndex]);//only support no-arg cmd + getvar_num = fastboot_getvar_list_size; } FB_DBG("getvar_num: %d\n", getvar_num); if (++cmdIndex > getvar_num) { @@ -789,10 +810,19 @@ chars_left -= strlen(cmd) + 1; } + fastboot_get_var(cmd, response, chars_left); + fastboot_tx_write_str(response); +} + +int fastboot_get_var(char *cmd, char *response, size_t chars_left) +{ + char *s1; + if (!strcmp_l1("version-baseband", cmd)) { strncat(response, "N/A", chars_left); } else if (!strcmp_l1("version-bootloader", cmd) || - !strcmp_l1("bootloader-version", cmd)) { + !strcmp_l1("bootloader-version", cmd) || + !strcmp_l1("u-boot-version", cmd)) { strncat(response, U_BOOT_VERSION, chars_left); } else if (!strcmp_l1("hw-revision", cmd)) { strncat(response, "vim3", chars_left); @@ -878,6 +908,7 @@ if (AbrGetSlotLastMarkedActive(&ops, &slot_index) != kAbrResultOk) { fastboot_fail("Failed to fetch last active slot"); + return -1; } else { const char *slot = AbrGetSlotSuffix(slot_index); strncat(response, slot + 1, chars_left); @@ -889,7 +920,7 @@ strsep(&cmd, ":"); if (!cmd) { fastboot_tx_write_str("FAILmissing partition name"); - return; + return -1; } char slotted_part[36]; @@ -903,7 +934,7 @@ } else { // If neither exists it's an unknown partition. fastboot_tx_write_str("FAILunknown partition"); - return; + return -1; } } else if (!strncmp("partition-size", cmd, strlen("partition-size"))) { char str_num[20]; @@ -912,11 +943,12 @@ const char *part = parse_fb_cmd_partition(cmd); if (!part) { - return; + return -1; } if (!strncmp("mbr", part, strlen("mbr"))) { strcpy(response, "FAILVariable not implemented"); + return -1; } else { if (!strcmp("bootloader", part)) { // boot0 and boot1 have the same size. @@ -939,7 +971,7 @@ FB_DBG("find_mmc_partition_by_name fail\n"); fastboot_tx_write_str( "FAILpartition does not exist"); - return; + return -1; } } strncat(response, str_num, chars_left); @@ -952,7 +984,7 @@ const char *part = parse_fb_cmd_partition(cmd); if (!part) { fastboot_tx_write_str("FAILpartition does not exist"); - return; + return -1; } // Fastboot doesn't know about any of our image formats so it's // all raw data as far as fastboot is concerned. @@ -976,9 +1008,10 @@ strsep(&cmd, ":"); FB_DBG("cmd is %s\n", cmd); - AbrSlotInfo *slot_info = get_slot_info(cmd); + AbrSlotInfo *slot_info = fastboot_get_slot_info(cmd); if (slot_info == NULL) { fastboot_fail("Invalid slot suffix"); + return -1; } else { strncat(response, slot_info->is_marked_successful ? "yes" : "no", @@ -991,9 +1024,10 @@ strsep(&cmd, ":"); FB_DBG("cmd is %s\n", cmd); - AbrSlotInfo *slot_info = get_slot_info(cmd); + AbrSlotInfo *slot_info = fastboot_get_slot_info(cmd); if (slot_info == NULL) { fastboot_fail("Invalid slot suffix"); + return -1; } else if (slot_info->is_bootable) { strncat(response, "N/A", chars_left); } else { @@ -1029,9 +1063,10 @@ strsep(&cmd, ":"); FB_DBG("cmd is %s\n", cmd); - AbrSlotInfo *slot_info = get_slot_info(cmd); + AbrSlotInfo *slot_info = fastboot_get_slot_info(cmd); if (slot_info == NULL) { fastboot_fail("Invalid slot suffix"); + return -1; } else { strncat(response, slot_info->is_bootable ? "no" : "yes", chars_left); @@ -1040,9 +1075,10 @@ strsep(&cmd, ":"); FB_DBG("cmd is %s\n", cmd); - AbrSlotInfo *slot_info = get_slot_info(cmd); + AbrSlotInfo *slot_info = fastboot_get_slot_info(cmd); if (slot_info == NULL) { fastboot_fail("Invalid slot suffix"); + return -1; } else { char buf[4]; sprintf(buf, "%d", slot_info->num_tries_remaining); @@ -1058,9 +1094,9 @@ } else { error("unknown variable: %s\n", cmd); strcpy(response, "FAILVariable not implemented"); + return -1; } - - fastboot_tx_write_str(response); + return 0; } static unsigned int rx_bytes_expected(void)
diff --git a/include/fb_fastboot.h b/include/fb_fastboot.h index ecced35..2106778 100644 --- a/include/fb_fastboot.h +++ b/include/fb_fastboot.h
@@ -21,8 +21,23 @@ #ifndef _FASTBOOT_H_ #define _FASTBOOT_H_ +#include <lib/abr/abr.h> + #define RESPONSE_LEN (64 + 1) void fastboot_fail(const char *s); void fastboot_okay(const char *s); +int fastboot_get_var(char *cmd, char *response, size_t chars_left); +extern const char fastboot_getvar_list[][RESPONSE_LEN]; +extern const size_t fastboot_getvar_list_size; +extern const char fastboot_getvar_list_dynamic[][RESPONSE_LEN]; +extern const size_t fastboot_getvar_list_dynamic_size; +extern const char fastboot_getvar_list_ab[][RESPONSE_LEN]; +extern const size_t fastboot_getvar_list_ab_size; +extern const char fastboot_getvar_list_ab_gbl_limited[][RESPONSE_LEN]; +extern const size_t fastboot_getvar_list_ab_gbl_limited_size; +// Returns slot info for the given slot string "a" or "b", or NULL on failure. +// The returned struct is only valid until the next call to this function. +AbrSlotInfo *fastboot_get_slot_info(const char *suffix); +const char *parse_fb_cmd_partition(char *cmd); #endif/*_FASTBOOT_H_*/
diff --git a/include/gbl_efi_common.h b/include/gbl_efi_common.h index a4ebbe0..93bc3d2 100644 --- a/include/gbl_efi_common.h +++ b/include/gbl_efi_common.h
@@ -1,7 +1,26 @@ /* - * Copyright (c) 2026 The Fuchsia Authors + * Copyright (C) 2024 The Android Open Source Project * - * SPDX-License-Identifier: BSD-3-Clause + * 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, embodiment or + * 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. + * + * SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause-Patent + * + * This file is dual-licensed under Apache 2.0 and BSD-2-Clause-Patent. + * You may choose to use this file under the terms of either: + * (a) the Apache License, Version 2.0, or + * (b) the BSD 2-Clause Patent License. + * + * Unless you expressly elect the BSD-2-Clause-Patent terms, the Apache-2.0 + * license terms apply by default. */ #ifndef __GBL_EFI_COMMON_H__
diff --git a/include/gbl_efi_fastboot_protocol.h b/include/gbl_efi_fastboot_protocol.h index be28fb7..3703def 100644 --- a/include/gbl_efi_fastboot_protocol.h +++ b/include/gbl_efi_fastboot_protocol.h
@@ -1,7 +1,26 @@ /* - * Copyright (c) 2026 The Fuchsia Authors + * Copyright (C) 2024 The Android Open Source Project * - * SPDX-License-Identifier: BSD-3-Clause + * 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, embodiment or + * 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. + * + * SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause-Patent + * + * This file is dual-licensed under Apache 2.0 and BSD-2-Clause-Patent. + * You may choose to use this file under the terms of either: + * (a) the Apache License, Version 2.0, or + * (b) the BSD 2-Clause Patent License. + * + * Unless you expressly elect the BSD-2-Clause-Patent terms, the Apache-2.0 + * license terms apply by default. */ #ifndef __GBL_EFI_FASTBOOT_PROTOCOL_H__
diff --git a/include/gbl_efi_fastboot_transport.h b/include/gbl_efi_fastboot_transport.h index 9fbcbf8..043f0fb 100644 --- a/include/gbl_efi_fastboot_transport.h +++ b/include/gbl_efi_fastboot_transport.h
@@ -1,7 +1,26 @@ /* - * Copyright (c) 2026 The Fuchsia Authors + * Copyright (C) 2024 The Android Open Source Project * - * SPDX-License-Identifier: BSD-3-Clause + * 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, embodiment or + * 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. + * + * SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause-Patent + * + * This file is dual-licensed under Apache 2.0 and BSD-2-Clause-Patent. + * You may choose to use this file under the terms of either: + * (a) the Apache License, Version 2.0, or + * (b) the BSD 2-Clause Patent License. + * + * Unless you expressly elect the BSD-2-Clause-Patent terms, the Apache-2.0 + * license terms apply by default. */ #include <efi_api.h>
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index e1933ee..82c31eb 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile
@@ -9,6 +9,7 @@ asflags-y += -DHOST_ARCH="$(HOST_ARCH)" -I. ccflags-y += -DHOST_ARCH="$(HOST_ARCH)" +CFLAGS_gbl_efi_fastboot.o += -I$(srctree)/lib/fuchsia/firmware_sdk/pkg/abr/include CFLAGS_efi_boottime.o += \ -DFW_VERSION="0x$(VERSION)" \ -DFW_PATCHLEVEL="0x$(PATCHLEVEL)"
diff --git a/lib/efi_loader/gbl_efi_fastboot.c b/lib/efi_loader/gbl_efi_fastboot.c index c32d066..e0d9857 100644 --- a/lib/efi_loader/gbl_efi_fastboot.c +++ b/lib/efi_loader/gbl_efi_fastboot.c
@@ -9,18 +9,70 @@ #include <gbl_efi_fastboot_protocol.h> #include <mmc.h> #include <amlogic/aml_mmc.h> +#include <version.h> +#include <g_dnl.h> +#include <fb_fastboot.h> +#include <partition_table.h> static efi_status_t EFIAPI get_var(struct GblEfiFastbootProtocol *self, size_t num_args, const char *const *args, size_t *buffer_size, char *buffer) { - return EFI_UNSUPPORTED; + EFI_ENTRY("%p, %zu, %p, %p, %p", self, num_args, args, buffer_size, buffer); + if (num_args == 0 || !args || !buffer_size || (*buffer_size > 0 && !buffer)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + char cmd_buf[RESPONSE_LEN]; + char resp_buf[RESPONSE_LEN] = ""; + snprintf(cmd_buf, sizeof(cmd_buf), "%s", args[0]); + + if (fastboot_get_var(cmd_buf, resp_buf, sizeof(resp_buf) - 1) != 0) + return EFI_EXIT(EFI_NOT_FOUND); + + size_t len = strlen(resp_buf); + if (*buffer_size < len + 1) { + *buffer_size = len + 1; + return EFI_EXIT(EFI_BUFFER_TOO_SMALL); + } + + strncpy(buffer, resp_buf, *buffer_size); + *buffer_size = len; + return EFI_EXIT(EFI_SUCCESS); } static efi_status_t EFIAPI get_var_all(struct GblEfiFastbootProtocol *self, void *context, GetVarAllCallback cb) { - return EFI_UNSUPPORTED; + EFI_ENTRY("%p, %p, %p", self, context, cb); + if (!cb) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + const char (*var_list)[RESPONSE_LEN]; + size_t var_list_size; + + if (has_boot_slot == 1) { + var_list = fastboot_getvar_list_ab_gbl_limited; + var_list_size = fastboot_getvar_list_ab_gbl_limited_size; + } else if (dynamic_partition) { + var_list = fastboot_getvar_list_dynamic; + var_list_size = fastboot_getvar_list_dynamic_size; + } else { + var_list = fastboot_getvar_list; + var_list_size = fastboot_getvar_list_size; + } + + for (size_t i = 0; i < var_list_size; i++) { + const char *name = var_list[i]; + char cmd_buf[RESPONSE_LEN]; + char resp_buf[RESPONSE_LEN] = ""; + snprintf(cmd_buf, sizeof(cmd_buf), "%s", name); + if (fastboot_get_var(cmd_buf, resp_buf, sizeof(resp_buf) - 1) == 0 && + strncmp(resp_buf, "FAIL", 4) != 0) { + const char *const args[] = { name }; + cb(context, 1, args, resp_buf); + } + } + return EFI_EXIT(EFI_SUCCESS); } static efi_status_t EFIAPI get_staged(struct GblEfiFastbootProtocol *self, @@ -34,7 +86,26 @@ const char *part_name, size_t *part_type_len, char *part_type) { - return EFI_UNSUPPORTED; + EFI_ENTRY("%p, %s, %p, %p", self, part_name, part_type_len, part_type); + if (!part_name || !part_type_len || (*part_type_len > 0 && !part_type)) + return EFI_EXIT(EFI_INVALID_PARAMETER); + + char cmd_buf[RESPONSE_LEN]; + snprintf(cmd_buf, sizeof(cmd_buf), "partition-type:%s", part_name); + const char *part = parse_fb_cmd_partition(cmd_buf); + if (!part) + return EFI_EXIT(EFI_NOT_FOUND); + + const char *type_str = "raw"; + size_t len = strlen(type_str); + if (*part_type_len < len + 1) { + *part_type_len = len + 1; + return EFI_EXIT(EFI_BUFFER_TOO_SMALL); + } + + strncpy(part_type, type_str, *part_type_len); + *part_type_len = len; + return EFI_EXIT(EFI_SUCCESS); } static efi_status_t handle_flash_bootloader(size_t download_buffer_used_size,