Home | History | Annotate | Download | only in HiKeyDxe
      1 /** @file
      2 *
      3 *  Copyright (c) 2015-2016, Linaro Ltd. All rights reserved.
      4 *  Copyright (c) 2015-2016, Hisilicon Ltd. All rights reserved.
      5 *
      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 <Library/BaseMemoryLib.h>
     17 #include <Library/BdsLib.h>
     18 #include <Library/CacheMaintenanceLib.h>
     19 #include <Library/DevicePathLib.h>
     20 #include <Library/MemoryAllocationLib.h>
     21 #include <Library/UefiBootServicesTableLib.h>
     22 #include <Library/UefiLib.h>
     23 #include <Library/UefiRuntimeServicesTableLib.h>
     24 
     25 #include <Guid/HiKeyVariable.h>
     26 
     27 #include <Protocol/BlockIo.h>
     28 #include <Protocol/DwUsb.h>
     29 
     30 #include "HiKeyDxeInternal.h"
     31 
     32 #define SERIAL_NUMBER_LENGTH        17
     33 #define SERIAL_NUMBER_LBA           1024
     34 #define SERIAL_NUMBER_BLOCK_SIZE    512
     35 #define RANDOM_MAGIC                0x9a4dbeaf
     36 
     37 struct RandomSerialNo {
     38   UINTN              Magic;
     39   UINTN              Data;
     40   CHAR8              SerialNo[32];
     41 };
     42 
     43 STATIC CHAR16 mSerialNo[17];
     44 
     45 STATIC
     46 UINTN
     47 EFIAPI
     48 HiKeyInitSerialNo (
     49   IN   VOID
     50   )
     51 {
     52   EFI_STATUS                      Status;
     53   UINTN                           VariableSize;
     54   EFI_DEVICE_PATH_PROTOCOL        *BlockDevicePath;
     55   EFI_BLOCK_IO_PROTOCOL           *BlockIoProtocol;
     56   EFI_HANDLE                      Handle;
     57   VOID                            *DataPtr;
     58   struct RandomSerialNo           *Random;
     59   CHAR16                          DefaultSerialNo[] = L"0123456789abcdef";
     60   CHAR16                          SerialNoUnicode[32], DataUnicode[32];
     61 
     62   BlockDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath));
     63   Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &BlockDevicePath, &Handle);
     64   if (EFI_ERROR (Status)) {
     65     DEBUG ((EFI_D_ERROR, "Warning: Couldn't locate block device (status: %r)\n", Status));
     66     return EFI_INVALID_PARAMETER;
     67   }
     68   Status = gBS->OpenProtocol (
     69 		      Handle,
     70                       &gEfiBlockIoProtocolGuid,
     71 		      (VOID **) &BlockIoProtocol,
     72                       gImageHandle,
     73                       NULL,
     74                       EFI_OPEN_PROTOCOL_GET_PROTOCOL
     75                       );
     76   if (EFI_ERROR (Status)) {
     77     DEBUG ((EFI_D_ERROR, "Warning: Couldn't open block device (status: %r)\n", Status));
     78     return EFI_DEVICE_ERROR;
     79   }
     80   DataPtr = AllocateZeroPool (SERIAL_NUMBER_BLOCK_SIZE);
     81   WriteBackDataCacheRange (DataPtr, SERIAL_NUMBER_BLOCK_SIZE);
     82   Status = BlockIoProtocol->ReadBlocks (BlockIoProtocol, BlockIoProtocol->Media->MediaId,
     83                                         SERIAL_NUMBER_LBA, SERIAL_NUMBER_BLOCK_SIZE,
     84                                         DataPtr);
     85   if (EFI_ERROR (Status)) {
     86     DEBUG ((EFI_D_ERROR, "Warning: failed on reading blocks.\n"));
     87     goto exit;
     88   }
     89   InvalidateDataCacheRange (DataPtr, SERIAL_NUMBER_BLOCK_SIZE);
     90   Random = (struct RandomSerialNo *)DataPtr;
     91   if (Random->Magic != RANDOM_MAGIC) {
     92     VariableSize = SERIAL_NUMBER_LENGTH * sizeof (CHAR16);
     93     Status = gRT->GetVariable (
     94                     (CHAR16 *)L"SerialNo",
     95                     &gHiKeyVariableGuid,
     96                     NULL,
     97                     &VariableSize,
     98                     &DefaultSerialNo
     99                     );
    100     if (Status == EFI_NOT_FOUND) {
    101       Status = gRT->SetVariable (
    102                       (CHAR16*)L"SerialNo",
    103                       &gHiKeyVariableGuid,
    104                       EFI_VARIABLE_NON_VOLATILE       |
    105                       EFI_VARIABLE_BOOTSERVICE_ACCESS |
    106                       EFI_VARIABLE_RUNTIME_ACCESS,
    107                       VariableSize,
    108                       DefaultSerialNo
    109                       );
    110     }
    111     CopyMem (mSerialNo, DefaultSerialNo, sizeof (DefaultSerialNo));
    112   } else {
    113     ZeroMem (DataUnicode, 32 * sizeof(CHAR16));
    114     ZeroMem (SerialNoUnicode, 32 * sizeof(CHAR16));
    115     AsciiStrToUnicodeStr (Random->SerialNo, SerialNoUnicode);
    116     VariableSize = SERIAL_NUMBER_LENGTH * sizeof (CHAR16);
    117     Status = gRT->GetVariable (
    118                     (CHAR16 *)L"SerialNo",
    119                     &gHiKeyVariableGuid,
    120                     NULL,
    121                     &VariableSize,
    122                     &DataUnicode
    123                     );
    124     if ((Status == EFI_NOT_FOUND) || StrCmp (DataUnicode, SerialNoUnicode)) {
    125       Status = gRT->SetVariable (
    126                       (CHAR16*)L"SerialNo",
    127                       &gHiKeyVariableGuid,
    128                       EFI_VARIABLE_NON_VOLATILE       |
    129                       EFI_VARIABLE_BOOTSERVICE_ACCESS |
    130                       EFI_VARIABLE_RUNTIME_ACCESS,
    131                       VariableSize,
    132                       SerialNoUnicode
    133                       );
    134     }
    135     CopyMem (mSerialNo, SerialNoUnicode, VariableSize);
    136   }
    137 exit:
    138   FreePool (DataPtr);
    139   return Status;
    140 }
    141 
    142 EFI_STATUS
    143 EFIAPI
    144 GetSerialNo (
    145   OUT CHAR16            *SerialNo,
    146   OUT UINT8             *Length
    147   )
    148 {
    149   EFI_STATUS             Status;
    150   UINTN                  VariableSize;
    151   CHAR16                 DataUnicode[32];
    152 
    153   if (SerialNo == NULL)
    154     return EFI_INVALID_PARAMETER;
    155   VariableSize = SERIAL_NUMBER_LENGTH * sizeof (CHAR16);
    156   ZeroMem (DataUnicode, 32 * sizeof(CHAR16));
    157   Status = gRT->GetVariable (
    158                   (CHAR16 *)L"SerialNo",
    159                   &gHiKeyVariableGuid,
    160                   NULL,
    161                   &VariableSize,
    162                   &DataUnicode
    163                   );
    164   if (EFI_ERROR (Status)) {
    165     return Status;
    166   }
    167   CopyMem (SerialNo, DataUnicode, VariableSize);
    168   *Length = VariableSize;
    169   return EFI_SUCCESS;
    170 }
    171 
    172 EFI_STATUS
    173 EFIAPI
    174 UsbPhyInit (
    175   IN UINT8     Mode
    176   )
    177 {
    178   return HiKeyUsbPhyInit (Mode);
    179 }
    180 
    181 DW_USB_PROTOCOL mDwUsbDevice = {
    182   GetSerialNo,
    183   UsbPhyInit
    184 };
    185 
    186 EFI_STATUS
    187 EFIAPI
    188 HiKeyEntryPoint (
    189   IN EFI_HANDLE         ImageHandle,
    190   IN EFI_SYSTEM_TABLE   *SystemTable
    191   )
    192 {
    193   EFI_STATUS           Status;
    194 
    195   Status = gBS->InstallProtocolInterface (
    196 		  &ImageHandle,
    197 		  &gDwUsbProtocolGuid,
    198 		  EFI_NATIVE_INTERFACE,
    199 		  &mDwUsbDevice
    200 		  );
    201   if (EFI_ERROR (Status)) {
    202     return Status;
    203   }
    204 
    205   HiKeyInitSerialNo ();
    206   HiKeyInitPeripherals ();
    207 
    208   Status = HiKeyBootMenuInstall ();
    209 
    210   return Status;
    211 }
    212