Home | History | Annotate | Download | only in PlatformBootManagerLib
      1 /** @file
      2   This file include all platform action which can be customized
      3   by IBV/OEM.
      4 
      5 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "PlatformBootManager.h"
     17 
     18 /**
     19   Perform the platform diagnostic, such like test memory. OEM/IBV also
     20   can customize this function to support specific platform diagnostic.
     21 
     22   @param MemoryTestLevel  The memory test intensive level
     23   @param QuietBoot        Indicate if need to enable the quiet boot
     24 
     25 **/
     26 VOID
     27 PlatformBootManagerDiagnostics (
     28   IN EXTENDMEM_COVERAGE_LEVEL    MemoryTestLevel,
     29   IN BOOLEAN                     QuietBoot
     30   )
     31 {
     32   EFI_STATUS                     Status;
     33 
     34   //
     35   // Here we can decide if we need to show
     36   // the diagnostics screen
     37   // Notes: this quiet boot code should be remove
     38   // from the graphic lib
     39   //
     40   if (QuietBoot) {
     41     BootLogoEnableLogo (ImageFormatBmp, PcdGetPtr(PcdLogoFile), EdkiiPlatformLogoDisplayAttributeCenter, 0, 0);
     42 
     43     //
     44     // Perform system diagnostic
     45     //
     46     Status = PlatformBootManagerMemoryTest (MemoryTestLevel);
     47     if (EFI_ERROR (Status)) {
     48       BootLogoDisableLogo ();
     49     }
     50 
     51     return;
     52   }
     53 
     54   //
     55   // Perform system diagnostic
     56   //
     57   Status = PlatformBootManagerMemoryTest (MemoryTestLevel);
     58 }
     59 
     60 /**
     61   Return the index of the load option in the load option array.
     62 
     63   The function consider two load options are equal when the
     64   OptionType, Attributes, Description, FilePath and OptionalData are equal.
     65 
     66   @param Key    Pointer to the load option to be found.
     67   @param Array  Pointer to the array of load options to be found.
     68   @param Count  Number of entries in the Array.
     69 
     70   @retval -1          Key wasn't found in the Array.
     71   @retval 0 ~ Count-1 The index of the Key in the Array.
     72 **/
     73 INTN
     74 PlatformFindLoadOption (
     75   IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Key,
     76   IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Array,
     77   IN UINTN                              Count
     78   )
     79 {
     80   UINTN                             Index;
     81 
     82   for (Index = 0; Index < Count; Index++) {
     83     if ((Key->OptionType == Array[Index].OptionType) &&
     84         (Key->Attributes == Array[Index].Attributes) &&
     85         (StrCmp (Key->Description, Array[Index].Description) == 0) &&
     86         (CompareMem (Key->FilePath, Array[Index].FilePath, GetDevicePathSize (Key->FilePath)) == 0) &&
     87         (Key->OptionalDataSize == Array[Index].OptionalDataSize) &&
     88         (CompareMem (Key->OptionalData, Array[Index].OptionalData, Key->OptionalDataSize) == 0)) {
     89       return (INTN) Index;
     90     }
     91   }
     92 
     93   return -1;
     94 }
     95 
     96 VOID
     97 PlatformRegisterFvBootOption (
     98   EFI_GUID                         *FileGuid,
     99   CHAR16                           *Description,
    100   UINT32                           Attributes
    101   )
    102 {
    103   EFI_STATUS                        Status;
    104   UINTN                             OptionIndex;
    105   EFI_BOOT_MANAGER_LOAD_OPTION      NewOption;
    106   EFI_BOOT_MANAGER_LOAD_OPTION      *BootOptions;
    107   UINTN                             BootOptionCount;
    108   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
    109   EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
    110   EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
    111 
    112   Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);
    113   ASSERT_EFI_ERROR (Status);
    114 
    115   EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
    116   DevicePath = AppendDevicePathNode (
    117                  DevicePathFromHandle (LoadedImage->DeviceHandle),
    118                  (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
    119                  );
    120 
    121   Status = EfiBootManagerInitializeLoadOption (
    122              &NewOption,
    123              LoadOptionNumberUnassigned,
    124              LoadOptionTypeBoot,
    125              Attributes,
    126              Description,
    127              DevicePath,
    128              NULL,
    129              0
    130              );
    131   if (!EFI_ERROR (Status)) {
    132     BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
    133 
    134     OptionIndex = PlatformFindLoadOption (&NewOption, BootOptions, BootOptionCount);
    135 
    136     if (OptionIndex == -1) {
    137       Status = EfiBootManagerAddLoadOptionVariable (&NewOption, (UINTN) -1);
    138       ASSERT_EFI_ERROR (Status);
    139     }
    140     EfiBootManagerFreeLoadOption (&NewOption);
    141     EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
    142   }
    143 }
    144 
    145 /**
    146   Do the platform specific action before the console is connected.
    147 
    148   Such as:
    149     Update console variable;
    150     Register new Driver#### or Boot####;
    151     Signal ReadyToLock event.
    152 **/
    153 VOID
    154 EFIAPI
    155 PlatformBootManagerBeforeConsole (
    156   VOID
    157   )
    158 {
    159   UINTN                        Index;
    160   EFI_STATUS                   Status;
    161   WIN_NT_SYSTEM_CONFIGURATION  *Configuration;
    162   EFI_INPUT_KEY                Enter;
    163   EFI_INPUT_KEY                F2;
    164   EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
    165 
    166   GetVariable2 (L"Setup", &gEfiWinNtSystemConfigGuid, (VOID **) &Configuration, NULL);
    167   if (Configuration != NULL) {
    168     //
    169     // SetupVariable is corrupt
    170     //
    171     Configuration->ConOutRow = PcdGet32 (PcdConOutColumn);
    172     Configuration->ConOutColumn = PcdGet32 (PcdConOutRow);
    173 
    174     Status = gRT->SetVariable (
    175                     L"Setup",
    176                     &gEfiWinNtSystemConfigGuid,
    177                     EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    178                     sizeof (WIN_NT_SYSTEM_CONFIGURATION),
    179                     Configuration
    180                     );
    181     if (EFI_ERROR (Status)) {
    182       DEBUG ((EFI_D_ERROR, "Failed to save Setup Variable to non-volatile storage, Status = %r\n", Status));
    183     }
    184     FreePool (Configuration);
    185   }
    186 
    187   //
    188   // Update the ocnsole variables.
    189   //
    190   for (Index = 0; gPlatformConsole[Index].DevicePath != NULL; Index++) {
    191     if ((gPlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
    192       EfiBootManagerUpdateConsoleVariable (ConIn, gPlatformConsole[Index].DevicePath, NULL);
    193     }
    194 
    195     if ((gPlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
    196       EfiBootManagerUpdateConsoleVariable (ConOut, gPlatformConsole[Index].DevicePath, NULL);
    197     }
    198 
    199     if ((gPlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
    200       EfiBootManagerUpdateConsoleVariable (ErrOut, gPlatformConsole[Index].DevicePath, NULL);
    201     }
    202   }
    203 
    204   //
    205   // Register ENTER as CONTINUE key
    206   //
    207   Enter.ScanCode    = SCAN_NULL;
    208   Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
    209   EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
    210   //
    211   // Map F2 to Boot Manager Menu
    212   //
    213   F2.ScanCode    = SCAN_F2;
    214   F2.UnicodeChar = CHAR_NULL;
    215   EfiBootManagerGetBootManagerMenu (&BootOption);
    216   EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL);
    217   //
    218   // Register UEFI Shell
    219   //
    220   PlatformRegisterFvBootOption (PcdGetPtr (PcdShellFile), L"UEFI Shell", LOAD_OPTION_ACTIVE);
    221 }
    222 
    223 /**
    224   Do the platform specific action after the console is connected.
    225 
    226   Such as:
    227     Dynamically switch output mode;
    228     Signal console ready platform customized event;
    229     Run diagnostics like memory testing;
    230     Connect certain devices;
    231     Dispatch aditional option roms.
    232 **/
    233 VOID
    234 EFIAPI
    235 PlatformBootManagerAfterConsole (
    236   VOID
    237   )
    238 {
    239   EFI_GRAPHICS_OUTPUT_BLT_PIXEL  Black;
    240   EFI_GRAPHICS_OUTPUT_BLT_PIXEL  White;
    241 
    242   Black.Blue = Black.Green = Black.Red = Black.Reserved = 0;
    243   White.Blue = White.Green = White.Red = White.Reserved = 0xFF;
    244 
    245   EfiBootManagerConnectAll ();
    246   EfiBootManagerRefreshAllBootOption ();
    247 
    248   PlatformBootManagerDiagnostics (QUICK, TRUE);
    249 
    250   PrintXY (10, 10, &White, &Black, L"F2    to enter Boot Manager Menu.                                            ");
    251   PrintXY (10, 30, &White, &Black, L"Enter to boot directly.");
    252 }
    253 
    254 /**
    255   This function is called each second during the boot manager waits the timeout.
    256 
    257   @param TimeoutRemain  The remaining timeout.
    258 **/
    259 VOID
    260 EFIAPI
    261 PlatformBootManagerWaitCallback (
    262   UINT16          TimeoutRemain
    263   )
    264 {
    265   EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;
    266   EFI_GRAPHICS_OUTPUT_BLT_PIXEL White;
    267   UINT16                        Timeout;
    268 
    269   Timeout = PcdGet16 (PcdPlatformBootTimeOut);
    270 
    271   Black.Blue = Black.Green = Black.Red = Black.Reserved = 0;
    272   White.Blue = White.Green = White.Red = White.Reserved = 0xFF;
    273 
    274   BootLogoUpdateProgress (
    275     White,
    276     Black,
    277     L"Start boot option",
    278     White,
    279     (Timeout - TimeoutRemain) * 100 / Timeout,
    280     0
    281     );
    282 }
    283