text: /** @file
  *
  *  Copyright (c) 2018, Linaro Ltd. All rights reserved.
  *
  *  This program and the accompanying materials
  *  are licensed and made available under the terms and conditions of the BSD License
  *  which accompanies this distribution.  The full text of the license may be found at
  *  http://opensource.org/licenses/bsd-license.php
  *
  *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  *
  **/
  
  #include <Guid/EventGroup.h>
  
  //#include <Hi3660.h>
  
  #include <Library/BaseLib.h>
  #include <Library/BaseMemoryLib.h>
  #include <Library/CacheMaintenanceLib.h>
  #include <Library/DebugLib.h>
  #include <Library/DevicePathLib.h>
  #include <Library/IoLib.h>
  #include <Library/MemoryAllocationLib.h>
  #include <Library/PrintLib.h>
  #include <Library/SerialPortLib.h>
  #include <Library/TimerLib.h>
  #include <Library/UefiBootManagerLib.h>
  #include <Library/UefiBootServicesTableLib.h>
  #include <Library/UefiLib.h>
  
  #include <Protocol/DevicePathFromText.h>
  #include <Protocol/EmbeddedGpio.h>
  #include <Protocol/LoadedImage.h>
  #include <Protocol/PlatformBootManager.h>
  #include <Protocol/PlatformVirtualKeyboard.h>
  
  #include "Rk3399Dxe.h"
  
  
  
  
  
  STATIC
  EFI_STATUS
  CreatePlatformBootOptionFromPath (
    IN     CHAR16                          *PathStr,
    IN     CHAR16                          *Description,
    IN OUT EFI_BOOT_MANAGER_LOAD_OPTION    *BootOption
    )
  {
    EFI_STATUS                   Status;
    EFI_DEVICE_PATH              *DevicePath;
  
    DevicePath = (EFI_DEVICE_PATH *)ConvertTextToDevicePath (PathStr);
    ASSERT (DevicePath != NULL);
    Status = EfiBootManagerInitializeLoadOption (
               BootOption,
               LoadOptionNumberUnassigned,
               LoadOptionTypeBoot,
               LOAD_OPTION_ACTIVE,
               Description,
               DevicePath,
               NULL,
               0
               );
    FreePool (DevicePath);
    return Status;
  }
  
  STATIC
  EFI_STATUS
  CreatePlatformBootOptionFromGuid (
    IN     EFI_GUID                        *FileGuid,
    IN     CHAR16                          *Description,
    IN OUT EFI_BOOT_MANAGER_LOAD_OPTION    *BootOption
    )
  {
    EFI_STATUS                             Status;
    EFI_DEVICE_PATH                        *DevicePath;
    EFI_DEVICE_PATH                        *TempDevicePath;
    EFI_LOADED_IMAGE_PROTOCOL              *LoadedImage;
    MEDIA_FW_VOL_FILEPATH_DEVICE_PATH      FileNode;
  
    Status = gBS->HandleProtocol (
                    gImageHandle,
                    &gEfiLoadedImageProtocolGuid,
                    (VOID **) &LoadedImage
                    );
    ASSERT_EFI_ERROR (Status);
    EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
    TempDevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
    ASSERT (TempDevicePath != NULL);
    DevicePath = AppendDevicePathNode (
                   TempDevicePath,
                   (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
                   );
    ASSERT (DevicePath != NULL);
    Status = EfiBootManagerInitializeLoadOption (
               BootOption,
               LoadOptionNumberUnassigned,
               LoadOptionTypeBoot,
               LOAD_OPTION_ACTIVE,
               Description,
               DevicePath,
               NULL,
               0
               );
    FreePool (DevicePath);
    return Status;
  }
  
  STATIC
  EFI_STATUS
  GetPlatformBootOptionsAndKeys (
    OUT UINTN                              *BootCount,
    OUT EFI_BOOT_MANAGER_LOAD_OPTION       **BootOptions,
    OUT EFI_INPUT_KEY                      **BootKeys
    )
  {
    EFI_GUID                               *FileGuid;
    CHAR16                                 *PathStr;
    EFI_STATUS                             Status;
    UINTN                                  Size;
  
    Size = sizeof (EFI_BOOT_MANAGER_LOAD_OPTION) * RK3399_BOOT_OPTION_NUM;
    *BootOptions = (EFI_BOOT_MANAGER_LOAD_OPTION *)AllocateZeroPool (Size);
    if (*BootOptions == NULL) {
      DEBUG ((DEBUG_ERROR, "Failed to allocate memory for BootOptions\n"));
      return EFI_OUT_OF_RESOURCES;
    }
    Size = sizeof (EFI_INPUT_KEY) * RK3399_BOOT_OPTION_NUM;
    *BootKeys = (EFI_INPUT_KEY *)AllocateZeroPool (Size);
    if (*BootKeys == NULL) {
      DEBUG ((DEBUG_ERROR, "Failed to allocate memory for BootKeys\n"));
      Status = EFI_OUT_OF_RESOURCES;
      goto Error;
    }
  
    PathStr = (CHAR16 *)PcdGetPtr (PcdSdBootDevicePath);
    ASSERT (PathStr != NULL);
    Status = CreatePlatformBootOptionFromPath (
               PathStr,
               L"Boot from SD",
               &(*BootOptions)[0]
               );
    ASSERT_EFI_ERROR (Status);
  
    PathStr = (CHAR16 *)PcdGetPtr (PcdAndroidBootDevicePath);
    ASSERT (PathStr != NULL);
    Status = CreatePlatformBootOptionFromPath (
               PathStr,
               L"Grub",
               &(*BootOptions)[1]
               );
    ASSERT_EFI_ERROR (Status);
  
    FileGuid = PcdGetPtr (PcdAndroidBootFile);
    ASSERT (FileGuid != NULL);
    Status = CreatePlatformBootOptionFromGuid (
               FileGuid,
               L"Android Boot",
               &(*BootOptions)[2]
               );
    ASSERT_EFI_ERROR (Status);
  
    FileGuid = PcdGetPtr (PcdAndroidFastbootFile);
    ASSERT (FileGuid != NULL);
    Status = CreatePlatformBootOptionFromGuid (
               FileGuid,
               L"Android Fastboot",
               &(*BootOptions)[3]
               );
    ASSERT_EFI_ERROR (Status);
    (*BootKeys)[3].ScanCode = SCAN_NULL;
    (*BootKeys)[3].UnicodeChar = 'f';
  
    *BootCount = 4;
  
    return EFI_SUCCESS;
  Error:
    FreePool (*BootOptions);
    return Status;
  }
  
  PLATFORM_BOOT_MANAGER_PROTOCOL mPlatformBootManager = {
    GetPlatformBootOptionsAndKeys
  };
  
  
  
  
  EFI_STATUS
  EFIAPI
  Rk3399EntryPoint (
    IN EFI_HANDLE         ImageHandle,
    IN EFI_SYSTEM_TABLE   *SystemTable
    )
  {
    EFI_STATUS            Status;
  
  
  
    Status = gBS->InstallProtocolInterface (
                    &ImageHandle,
                    &gPlatformBootManagerProtocolGuid,
                    EFI_NATIVE_INTERFACE,
                    &mPlatformBootManager
                    );
    return Status;
  }
  