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
HiKeyInitSerialNo(IN VOID)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
GetSerialNo(OUT CHAR16 * SerialNo,OUT UINT8 * Length)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
UsbPhyInit(IN UINT8 Mode)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
HiKeyEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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