efi_loader: nocolor command line attr for initrddump.efi
authorHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Sun, 20 Mar 2022 08:21:57 +0000 (09:21 +0100)
committerHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Sat, 26 Mar 2022 06:46:21 +0000 (07:46 +0100)
initrddump.efi uses colored output and clear the screen. This is not
helpful for integration into Python tests. Allow specifying 'nocolor' in
the load option data to suppress color output and clearing the screen.

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
lib/efi_loader/initrddump.c

index 7de43bc..6f8dd09 100644 (file)
@@ -4,6 +4,9 @@
  *
  * initrddump.efi saves the initial RAM disk provided via the
  * EFI_LOAD_FILE2_PROTOCOL.
+ *
+ * Specifying 'nocolor' as load option data suppresses colored output and
+ * clearing of the screen.
  */
 
 #include <common.h>
@@ -25,6 +28,7 @@ static const efi_guid_t guid_simple_file_system_protocol =
                                        EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
 static const efi_guid_t load_file2_guid = EFI_LOAD_FILE2_PROTOCOL_GUID;
 static efi_handle_t handle;
+static bool nocolor;
 
 /*
  * Device path defined by Linux to identify the handle providing the
@@ -47,6 +51,17 @@ static const struct efi_initrd_dp initrd_dp = {
 };
 
 /**
+ * color() - set foreground color
+ *
+ * @color:     foreground color
+ */
+static void color(u8 color)
+{
+       if (!nocolor)
+               cout->set_attribute(cout, color | EFI_BACKGROUND_BLACK);
+}
+
+/**
  * print() - print string
  *
  * @string:    text
@@ -57,15 +72,26 @@ static void print(u16 *string)
 }
 
 /**
+ * cls() - clear screen
+ */
+static void cls(void)
+{
+       if (nocolor)
+               print(u"\r\n");
+       else
+               cout->clear_screen(cout);
+}
+
+/**
  * error() - print error string
  *
  * @string:    error text
  */
 static void error(u16 *string)
 {
-       cout->set_attribute(cout, EFI_LIGHTRED | EFI_BACKGROUND_BLACK);
+       color(EFI_LIGHTRED);
        print(string);
-       cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+       color(EFI_LIGHTBLUE);
 }
 
 /*
@@ -215,10 +241,13 @@ static u16 *skip_whitespace(u16 *pos)
  *
  * @string:    string to search for keyword
  * @keyword:   keyword to be searched
- * Return:     true fi @string starts with the keyword
+ * Return:     true if @string starts with the keyword
  */
 static bool starts_with(u16 *string, u16 *keyword)
 {
+       if (!string || !keyword)
+               return false;
+
        for (; *keyword; ++string, ++keyword) {
                if (*string != *keyword)
                        return false;
@@ -401,6 +430,30 @@ out:
 }
 
 /**
+ * get_load_options() - get load options
+ *
+ * Return:     load options or NULL
+ */
+u16 *get_load_options(void)
+{
+       efi_status_t ret;
+       struct efi_loaded_image *loaded_image;
+
+       ret = bs->open_protocol(handle, &loaded_image_guid,
+                               (void **)&loaded_image, NULL, NULL,
+                               EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+       if (ret != EFI_SUCCESS) {
+               error(u"Loaded image protocol not found\r\n");
+               return NULL;
+       }
+
+       if (!loaded_image->load_options_size || !loaded_image->load_options)
+               return NULL;
+
+       return loaded_image->load_options;
+}
+
+/**
  * efi_main() - entry point of the EFI application.
  *
  * @handle:    handle of the loaded image
@@ -410,18 +463,23 @@ out:
 efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
                             struct efi_system_table *systab)
 {
+       u16 *load_options;
+
        handle = image_handle;
        systable = systab;
        cerr = systable->std_err;
        cout = systable->con_out;
        cin = systable->con_in;
        bs = systable->boottime;
+       load_options = get_load_options();
 
-       cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
-       cout->clear_screen(cout);
-       cout->set_attribute(cout, EFI_WHITE | EFI_BACKGROUND_BLACK);
+       if (starts_with(load_options, u"nocolor"))
+               nocolor = true;
+
+       color(EFI_WHITE);
+       cls();
        print(u"INITRD Dump\r\n===========\r\n\r\n");
-       cout->set_attribute(cout, EFI_LIGHTBLUE | EFI_BACKGROUND_BLACK);
+       color(EFI_LIGHTBLUE);
 
        for (;;) {
                u16 command[BUFFER_SIZE];
@@ -443,7 +501,8 @@ efi_status_t EFIAPI efi_main(efi_handle_t image_handle,
                        do_help();
        }
 
-       cout->set_attribute(cout, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
-       cout->clear_screen(cout);
+       color(EFI_LIGHTGRAY);
+       cls();
+
        return EFI_SUCCESS;
 }