Commit 7b6d9681 authored by Mario Limonciello's avatar Mario Limonciello
parent 1dd6bbda
From 9bebde2c8b8960d86326f805743edb9293a6d173 Mon Sep 17 00:00:00 2001
From: Ivan Hu <ivan.hu@canonical.com>
Date: Thu, 22 Jun 2017 17:06:41 +0800
Subject: [PATCH 1/2] efi: delete boot entry before apply capsule
Some buggy firmwares were found that if apply capsule fail will keep boot to
Linux-Firmware-Updater boot entry that created by fwupdate. This patch will
check the boot entry and delete it before the capsules was applied, since it has
been no use after Linux-Firmware-Updater was booted from it.
Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
---
efi/fwupdate.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 123 insertions(+)
diff --git a/efi/fwupdate.c b/efi/fwupdate.c
index d009267..bf41a12 100644
--- a/efi/fwupdate.c
+++ b/efi/fwupdate.c
@@ -665,6 +665,119 @@ open_file(EFI_DEVICE_PATH *dp, EFI_FILE_HANDLE *fh)
}
static EFI_STATUS
+delete_boot_entry(void)
+{
+ EFI_STATUS rc;
+
+ UINTN variable_name_allocation = GNVN_BUF_SIZE;
+ UINTN variable_name_size = 0;
+ CHAR16 *variable_name;
+ EFI_GUID vendor_guid = empty_guid;
+ UINTN mult_res;
+ EFI_STATUS ret = EFI_OUT_OF_RESOURCES;
+
+ variable_name = AllocateZeroPool(GNVN_BUF_SIZE * 2);
+ if (!variable_name) {
+ Print(L"%a:%a():%d: Tried to allocate %d\n",
+ __FILE__, __func__, __LINE__,
+ GNVN_BUF_SIZE * 2);
+ Print(L"Could not allocate memory.\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ while (1) {
+ variable_name_size = variable_name_allocation;
+ rc = uefi_call_wrapper(RT->GetNextVariableName, 3,
+ &variable_name_size, variable_name,
+ &vendor_guid);
+ if (rc == EFI_BUFFER_TOO_SMALL) {
+
+ UINTN new_allocation;
+ CHAR16 *new_name;
+
+ new_allocation = variable_name_size;
+ if (uintn_mult(new_allocation, 2, &mult_res)) {
+ Print(L"%a:%a():%d: %d * 2 would overflow size\n",
+ __FILE__, __func__, __LINE__,
+ new_allocation);
+ ret = EFI_OUT_OF_RESOURCES;
+ goto err;
+ }
+ new_name = AllocatePool(new_allocation * 2);
+ if (!new_name) {
+ Print(L"%a:%a():%d: Tried to allocate %d\n",
+ __FILE__, __func__, __LINE__,
+ new_allocation * 2);
+ Print(L"Could not allocate memory.\n");
+ ret = EFI_OUT_OF_RESOURCES;
+ goto err;
+ }
+ CopyMem(new_name, variable_name,
+ variable_name_allocation);
+ variable_name_allocation = new_allocation;
+ FreePool(variable_name);
+ variable_name = new_name;
+ continue;
+ } else if (rc == EFI_NOT_FOUND) {
+ break;
+ } else if (EFI_ERROR(rc)) {
+ Print(L"%a:%a():%d: "
+ L"Could not get variable name: %r\n",
+ __FILE__, __func__, __LINE__, rc);
+ ret = rc;
+ goto err;
+ }
+
+ /* check if the variable name is Boot#### */
+ UINTN vns = StrLen(variable_name);
+ if (vns == 8 && CompareMem(variable_name, L"Boot", 8) == 0) {
+ UINTN info_size = 0;
+ UINT32 attributes = 0;
+ void *info_ptr = NULL;
+ CHAR16 *load_op_description = NULL;
+
+ rc = read_variable(variable_name, vendor_guid, &info_ptr,
+ &info_size, &attributes);
+ if (EFI_ERROR(rc)) {
+ ret = rc;
+ goto err;
+ }
+
+ /*
+ * check if the boot path created by fwupdate,
+ * check with EFI_LOAD_OPTION decription
+ */
+ load_op_description = (CHAR16 *)((UINT8 *)info_ptr +
+ sizeof(UINT32) + sizeof(UINT16));
+
+ if (CompareMem(load_op_description,
+ L"Linux-Firmware-Updater",
+ sizeof (L"Linux-Firmware-Updater") - 2)
+ == 0) {
+ delete_variable(variable_name, vendor_guid,
+ attributes);
+
+ FreePool(info_ptr);
+ goto out;
+
+ }
+
+ FreePool(info_ptr);
+ }
+ }
+
+out:
+ FreePool(variable_name);
+ return EFI_SUCCESS;
+
+err:
+ FreePool(variable_name);
+
+ return ret;
+}
+
+
+static EFI_STATUS
add_capsule(update_table *update, EFI_CAPSULE_HEADER **capsule_out,
EFI_CAPSULE_BLOCK_DESCRIPTOR *cbd_out)
{
@@ -756,6 +869,16 @@ apply_capsules(EFI_CAPSULE_HEADER **capsules,
UINT64 max_capsule_size;
EFI_STATUS rc;
+ rc = delete_boot_entry();
+ if (EFI_ERROR(rc)) {
+ /*
+ * Print out deleting boot entry error, but still try to apply
+ * capsule.
+ */
+ Print(L"%a:%a():%d: Could not delete boot entry: %r\n",
+ __FILE__, __func__, __LINE__, rc);
+ }
+
rc = uefi_call_wrapper(RT->QueryCapsuleCapabilities, 4, capsules,
num_updates, &max_capsule_size, reset);
if (debugging) {
--
2.7.4
From cd9ea4cbdc93da922ce9abc45c7de63fe252ecc8 Mon Sep 17 00:00:00 2001
From: Ivan Hu <ivan.hu@canonical.com>
Date: Fri, 30 Jun 2017 16:04:24 +0800
Subject: [PATCH 2/2] efi: delete the boot path from the BootOrder list
The patch needs to follow the patch 49a5df9845b5b9739f1355580cd65ba57d5b85fe
efi: delete boot entry before apply capsule, which will delete the boot patch
created by fwupdate before applying capsule. This patch alse deletes the end
BootOrder.
Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
---
efi/fwupdate.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 85 insertions(+), 4 deletions(-)
diff --git a/efi/fwupdate.c b/efi/fwupdate.c
index bf41a12..2cd1890 100644
--- a/efi/fwupdate.c
+++ b/efi/fwupdate.c
@@ -665,6 +665,71 @@ open_file(EFI_DEVICE_PATH *dp, EFI_FILE_HANDLE *fh)
}
static EFI_STATUS
+delete_boot_order(CHAR16 *name, EFI_GUID guid)
+{
+
+ UINTN i;
+ UINT16 boot_num;
+ EFI_STATUS rc;
+ UINTN info_size = 0;
+ UINT32 attributes = 0;
+ void *info_ptr = NULL;
+ UINT16 *new_info_ptr = NULL;
+ BOOLEAN num_found = FALSE;
+ UINTN new_list_num = 0;
+
+ /* get boot hex number */
+ boot_num = xtoi((CHAR16 *)((UINT8 *)name + sizeof(L"Boot")));
+
+ rc = read_variable(L"BootOrder", guid, &info_ptr, &info_size,
+ &attributes);
+ if (EFI_ERROR(rc))
+ return rc;
+
+ new_info_ptr = AllocatePool(info_size);
+ if (!new_info_ptr) {
+ Print(L"%a:%a():%d: Tried to allocate %d\n",
+ __FILE__, __func__, __LINE__, info_size);
+ Print(L"Could not allocate memory.\n");
+ FreePool(info_ptr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (i = 0; i < (info_size / sizeof(UINT16)) ; i++) {
+ if (((UINT16 *)info_ptr)[i] != boot_num) {
+ new_info_ptr[i] = ((UINT16 *)info_ptr)[i];
+ new_list_num++;
+
+ } else {
+ num_found = TRUE;
+ }
+ }
+
+ /* if not in the BootOrder list, do not update BootOrder */
+ if (!num_found) {
+ rc = EFI_SUCCESS;
+ goto out;
+ }
+
+ rc = uefi_call_wrapper(RT->SetVariable, 5, L"BootOrder", &guid,
+ attributes, new_list_num * sizeof(UINT16),
+ new_info_ptr);
+ if (EFI_ERROR(rc)) {
+ Print(L"%a:%a():%d: Could not update variable "
+ L"status for \"%s\": %r\n",
+ __FILE__, __func__, __LINE__, name, rc);
+ goto out;
+ }
+
+out:
+
+ FreePool(info_ptr);
+ FreePool(new_info_ptr);
+
+ return rc;
+}
+
+static EFI_STATUS
delete_boot_entry(void)
{
EFI_STATUS rc;
@@ -754,12 +819,28 @@ delete_boot_entry(void)
L"Linux-Firmware-Updater",
sizeof (L"Linux-Firmware-Updater") - 2)
== 0) {
- delete_variable(variable_name, vendor_guid,
+ rc = delete_variable(variable_name, vendor_guid,
attributes);
- FreePool(info_ptr);
- goto out;
-
+ if (EFI_ERROR(rc)) {
+ Print(L"fail to delete Linux-Firmware-"
+ L"Updater boot path.\n");
+ FreePool(info_ptr);
+ ret = rc;
+ goto out;
+ }
+
+ /* delete the boot path from BootOrder list */
+ rc = delete_boot_order(variable_name,
+ vendor_guid);
+
+ if (EFI_ERROR(rc)) {
+ Print(L"fail to delete the boot path "
+ L"from BootOrder boot path.\n");
+ FreePool(info_ptr);
+ ret = rc;
+ goto out;
+ }
}
FreePool(info_ptr);
--
2.7.4
uninitialized_boot_next.patch
0001-Fix-sprintf-formatting-for-Boot.patch
0001-efi-delete-boot-entry-before-apply-capsule.patch
0002-efi-delete-the-boot-path-from-the-BootOrder-list.patch
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment