Export the kernel partition's UniqueGuid to the kernel command line.
This will cause a %U in the kernel command line to be replaced with the
human-readable form of the kernel partition's UniqueGuid, which is passed
from the Chrome OS BIOS. If the BIOS doesn't pass this information (older
ones don't), %U expands to 00000000-0000-0000-0000-000000000000.
BUG=chromium-os:4941
Review URL: http://codereview.chromium.org/2832078
diff --git a/bootstub.c b/bootstub.c
index e98dd36..85aa219 100644
--- a/bootstub.c
+++ b/bootstub.c
@@ -44,10 +44,59 @@
return (struct hacked_params *)(bootstub_location - 0x1000);
}
+// Copy a string to the right within a buffer.
+static void shove_over(char *src, char *dst)
+{
+ int i = 0;
+ for (i=0; src[i]; i++)
+ ; // find strlen(src)
+ dst += i;
+ src += i;
+ i++; // also terminating '\0';
+ while (i--)
+ *dst-- = *src--;
+}
+
+// sprintf(dst,"%02x",val)
+static void one_byte(char *dst, uint8_t val)
+{
+ dst[0] = "0123456789abcdef"[(val >> 4) & 0x0F];
+ dst[1] = "0123456789abcdef"[val & 0x0F];
+}
+
+// Display a GUID in canonical form
+static void emit_guid(char *dst, uint8_t *guid)
+{
+ one_byte(dst, guid[3]); dst += 2;
+ one_byte(dst, guid[2]); dst += 2;
+ one_byte(dst, guid[1]); dst += 2;
+ one_byte(dst, guid[0]); dst += 2;
+ *dst++ = '-';
+ one_byte(dst, guid[5]); dst += 2;
+ one_byte(dst, guid[4]); dst += 2;
+ *dst++ = '-';
+ one_byte(dst, guid[7]); dst += 2;
+ one_byte(dst, guid[6]); dst += 2;
+ *dst++ = '-';
+ one_byte(dst, guid[8]); dst += 2;
+ one_byte(dst, guid[9]); dst += 2;
+ *dst++ = '-';
+ one_byte(dst, guid[10]); dst += 2;
+ one_byte(dst, guid[11]); dst += 2;
+ one_byte(dst, guid[12]); dst += 2;
+ one_byte(dst, guid[13]); dst += 2;
+ one_byte(dst, guid[14]); dst += 2;
+ one_byte(dst, guid[15]); dst += 2;
+}
+
+
// Replace any %D with the device letter, and replace any %P with the partition
-// number. For example, ("root=/dev/sd%D%P",2,3) gives "root=/dev/sdc3". The
-// input string must be mutable and end with a trailing '\0'.
-void update_cmdline_inplace(char *src, int devnum, int partnum)
+// number. For example, ("root=/dev/sd%D%P",2,3) gives "root=/dev/sdc3".
+// Replace any %U with the human-readable form of the GUID (if provided). The
+// input string must be mutable and end with a trailing '\0', and have enough
+// room for all the expansion.
+static void update_cmdline_inplace(char *src, int devnum, int partnum,
+ uint8_t *guid)
{
char *dst;
@@ -74,6 +123,13 @@
*dst = 'a' + devnum;
src++;
break;
+ case 'U':
+ if (guid) {
+ shove_over(src+2, dst+36);
+ emit_guid(dst, guid);
+ src = dst+35;
+ dst += 35;
+ }
default:
*dst = *src;
}
@@ -95,7 +151,7 @@
extern void trampoline(unsigned long, void *);
-// Reserve some space for the EFI memory map.
+// Reserve some space for the EFI memory map.
// Danger Will Robinson: this is just a guess at the size and alignment. If
// it's too small, the EFI GetMemoryMap() call will fail.
// FIXME: Make the size dynamic? Retry with larger size on failure?
@@ -106,6 +162,9 @@
UINTN drive_number; // 0 - 25
UINTN partition_number; // 1 - 99
UINTN original_address; // our RAM address prior to execution
+ // The guid stuff was added later, so we need to consider it optional, at
+ // least for testing.
+ uint8_t partition_guid[16]; // kernel partition GUID
} cros_boot_info_t;
@@ -119,6 +178,8 @@
UINT32 desc_version = 0;
EFI_LOADED_IMAGE *loaded_image;
EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
+ EFI_GUID zero_guid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
+ void *guid_ptr;
// I'm here.
port80w(0xc0de);
@@ -134,6 +195,10 @@
goto fail;
}
cros_boot_info_t *booting = loaded_image->LoadOptions;
+ if (loaded_image->LoadOptionsSize < 40) // DWR: min size including guid
+ guid_ptr = &zero_guid;
+ else
+ guid_ptr = booting->partition_guid;
// Find the parameters that we're passing to the kernel.
struct hacked_params *params = find_params_struct(booting->original_address);
@@ -141,7 +206,8 @@
// Update the kernel command-line string with the correct rootfs device
update_cmdline_inplace((char *)(unsigned long)(params->cmd_line_ptr),
booting->drive_number,
- booting->partition_number + 1);
+ booting->partition_number + 1,
+ guid_ptr);
// Obtain the EFI memory map.
if (uefi_call_wrapper(systab->BootServices->GetMemoryMap, 5,