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