]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPkg/Library/BdsLib/BdsHelper.c
ArmPkg: Introduce GetGlobalEnvironmentVariable() function.
[mirror_edk2.git] / ArmPkg / Library / BdsLib / BdsHelper.c
CommitLineData
1e57a462 1/** @file\r
2*\r
c0b2e477 3* Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
1e57a462 4*\r
c0b2e477 5* This program and the accompanying materials\r
6* are licensed and made available under the terms and conditions of the BSD License\r
7* which accompanies this distribution. The full text of the license may be found at\r
8* http://opensource.org/licenses/bsd-license.php\r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
1e57a462 12*\r
13**/\r
14\r
15#include "BdsInternal.h"\r
16\r
17#include <Library/DxeServicesTableLib.h>\r
18#include <Library/HobLib.h>\r
19#include <Library/TimerLib.h>\r
20#include <Library/PrintLib.h>\r
21#include <Library/SerialPortLib.h>\r
22\r
23STATIC CHAR8 *mTokenList[] = {\r
24 /*"SEC",*/\r
25 "PEI",\r
26 "DXE",\r
27 "BDS",\r
28 NULL\r
29};\r
30\r
31EFI_STATUS\r
32ShutdownUefiBootServices (\r
33 VOID\r
34 )\r
35{\r
36 EFI_STATUS Status;\r
37 UINTN MemoryMapSize;\r
38 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
39 UINTN MapKey;\r
40 UINTN DescriptorSize;\r
41 UINT32 DescriptorVersion;\r
42 UINTN Pages;\r
43\r
44 MemoryMap = NULL;\r
45 MemoryMapSize = 0;\r
46 Pages = 0;\r
47\r
48 do {\r
49 Status = gBS->GetMemoryMap (\r
50 &MemoryMapSize,\r
51 MemoryMap,\r
52 &MapKey,\r
53 &DescriptorSize,\r
54 &DescriptorVersion\r
55 );\r
56 if (Status == EFI_BUFFER_TOO_SMALL) {\r
57\r
58 Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;\r
59 MemoryMap = AllocatePages (Pages);\r
60\r
61 //\r
62 // Get System MemoryMap\r
63 //\r
64 Status = gBS->GetMemoryMap (\r
65 &MemoryMapSize,\r
66 MemoryMap,\r
67 &MapKey,\r
68 &DescriptorSize,\r
69 &DescriptorVersion\r
70 );\r
71 }\r
72\r
73 // Don't do anything between the GetMemoryMap() and ExitBootServices()\r
74 if (!EFI_ERROR(Status)) {\r
75 Status = gBS->ExitBootServices (gImageHandle, MapKey);\r
76 if (EFI_ERROR(Status)) {\r
77 FreePages (MemoryMap, Pages);\r
78 MemoryMap = NULL;\r
79 MemoryMapSize = 0;\r
80 }\r
81 }\r
82 } while (EFI_ERROR(Status));\r
83\r
84 return Status;\r
85}\r
86\r
87/**\r
88 Connect all DXE drivers\r
89\r
90 @retval EFI_SUCCESS All drivers have been connected\r
91 @retval EFI_NOT_FOUND No handles match the search.\r
92 @retval EFI_OUT_OF_RESOURCES There is not resource pool memory to store the matching results.\r
93\r
94**/\r
95EFI_STATUS\r
96BdsConnectAllDrivers (\r
97 VOID\r
98 )\r
99{\r
100 UINTN HandleCount, Index;\r
101 EFI_HANDLE *HandleBuffer;\r
102 EFI_STATUS Status;\r
103\r
104 do {\r
105 // Locate all the driver handles\r
106 Status = gBS->LocateHandleBuffer (\r
107 AllHandles,\r
108 NULL,\r
109 NULL,\r
110 &HandleCount,\r
111 &HandleBuffer\r
112 );\r
113 if (EFI_ERROR (Status)) {\r
114 break;\r
115 }\r
116\r
117 // Connect every handles\r
118 for (Index = 0; Index < HandleCount; Index++) {\r
119 gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
120 }\r
121\r
122 if (HandleBuffer != NULL) {\r
123 FreePool (HandleBuffer);\r
124 }\r
125\r
126 // Check if new handles have been created after the start of the previous handles\r
127 Status = gDS->Dispatch ();\r
128 } while (!EFI_ERROR(Status));\r
129\r
130 return EFI_SUCCESS;\r
131}\r
132\r
133STATIC\r
134EFI_STATUS\r
135InsertSystemMemoryResources (\r
136 LIST_ENTRY *ResourceList,\r
137 EFI_HOB_RESOURCE_DESCRIPTOR *ResHob\r
138 )\r
139{\r
140 BDS_SYSTEM_MEMORY_RESOURCE *NewResource;\r
141 LIST_ENTRY *Link;\r
142 LIST_ENTRY *NextLink;\r
143 LIST_ENTRY AttachedResources;\r
144 BDS_SYSTEM_MEMORY_RESOURCE *Resource;\r
145 EFI_PHYSICAL_ADDRESS NewResourceEnd;\r
146\r
147 if (IsListEmpty (ResourceList)) {\r
148 NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));\r
149 NewResource->PhysicalStart = ResHob->PhysicalStart;\r
150 NewResource->ResourceLength = ResHob->ResourceLength;\r
151 InsertTailList (ResourceList, &NewResource->Link);\r
152 return EFI_SUCCESS;\r
153 }\r
154\r
155 InitializeListHead (&AttachedResources);\r
156\r
157 Link = ResourceList->ForwardLink;\r
158 ASSERT (Link != NULL);\r
159 while (Link != ResourceList) {\r
160 Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;\r
161\r
162 // Sanity Check. The resources should not overlapped.\r
163 ASSERT(!((ResHob->PhysicalStart >= Resource->PhysicalStart) && (ResHob->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))));\r
164 ASSERT(!((ResHob->PhysicalStart + ResHob->ResourceLength - 1 >= Resource->PhysicalStart) &&\r
165 ((ResHob->PhysicalStart + ResHob->ResourceLength - 1) < (Resource->PhysicalStart + Resource->ResourceLength))));\r
166\r
167 // The new resource is attached after this resource descriptor\r
168 if (ResHob->PhysicalStart == Resource->PhysicalStart + Resource->ResourceLength) {\r
169 Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength;\r
170\r
171 NextLink = RemoveEntryList (&Resource->Link);\r
172 InsertTailList (&AttachedResources, &Resource->Link);\r
173 Link = NextLink;\r
174 }\r
175 // The new resource is attached before this resource descriptor\r
176 else if (ResHob->PhysicalStart + ResHob->ResourceLength == Resource->PhysicalStart) {\r
177 Resource->PhysicalStart = ResHob->PhysicalStart;\r
178 Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength;\r
179\r
180 NextLink = RemoveEntryList (&Resource->Link);\r
181 InsertTailList (&AttachedResources, &Resource->Link);\r
182 Link = NextLink;\r
183 } else {\r
184 Link = Link->ForwardLink;\r
185 }\r
186 }\r
187\r
188 if (!IsListEmpty (&AttachedResources)) {\r
189 // See if we can merge the attached resource with other resources\r
190\r
191 NewResource = (BDS_SYSTEM_MEMORY_RESOURCE*)GetFirstNode (&AttachedResources);\r
192 Link = RemoveEntryList (&NewResource->Link);\r
193 while (!IsListEmpty (&AttachedResources)) {\r
194 // Merge resources\r
195 Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;\r
196\r
197 // Ensure they overlap each other\r
198 ASSERT(\r
199 ((NewResource->PhysicalStart >= Resource->PhysicalStart) && (NewResource->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))) ||\r
200 (((NewResource->PhysicalStart + NewResource->ResourceLength) >= Resource->PhysicalStart) && ((NewResource->PhysicalStart + NewResource->ResourceLength) < (Resource->PhysicalStart + Resource->ResourceLength)))\r
201 );\r
202\r
203 NewResourceEnd = MAX (NewResource->PhysicalStart + NewResource->ResourceLength, Resource->PhysicalStart + Resource->ResourceLength);\r
204 NewResource->PhysicalStart = MIN (NewResource->PhysicalStart, Resource->PhysicalStart);\r
205 NewResource->ResourceLength = NewResourceEnd - NewResource->PhysicalStart;\r
206\r
207 Link = RemoveEntryList (Link);\r
208 }\r
209 } else {\r
210 // None of the Resource of the list is attached to this ResHob. Create a new entry for it\r
211 NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));\r
212 NewResource->PhysicalStart = ResHob->PhysicalStart;\r
213 NewResource->ResourceLength = ResHob->ResourceLength;\r
214 }\r
215 InsertTailList (ResourceList, &NewResource->Link);\r
216 return EFI_SUCCESS;\r
217}\r
218\r
219EFI_STATUS\r
220GetSystemMemoryResources (\r
221 IN LIST_ENTRY *ResourceList\r
222 )\r
223{\r
224 EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;\r
225\r
226 InitializeListHead (ResourceList);\r
227\r
228 // Find the first System Memory Resource Descriptor\r
229 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);\r
230 while ((ResHob != NULL) && (ResHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)) {\r
231 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));\r
232 }\r
233\r
234 // Did not find any\r
235 if (ResHob == NULL) {\r
236 return EFI_NOT_FOUND;\r
237 } else {\r
238 InsertSystemMemoryResources (ResourceList, ResHob);\r
239 }\r
240\r
241 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));\r
242 while (ResHob != NULL) {\r
243 if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
244 InsertSystemMemoryResources (ResourceList, ResHob);\r
245 }\r
246 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));\r
247 }\r
248\r
249 return EFI_SUCCESS;\r
250}\r
251\r
252VOID\r
253PrintPerformance (\r
254 VOID\r
255 )\r
256{\r
257 UINTN Key;\r
258 CONST VOID *Handle;\r
259 CONST CHAR8 *Token, *Module;\r
260 UINT64 Start, Stop, TimeStamp;\r
261 UINT64 Delta, TicksPerSecond, Milliseconds;\r
262 UINTN Index;\r
263 CHAR8 Buffer[100];\r
264 UINTN CharCount;\r
265 BOOLEAN CountUp;\r
266\r
267 TicksPerSecond = GetPerformanceCounterProperties (&Start, &Stop);\r
268 if (Start < Stop) {\r
269 CountUp = TRUE;\r
270 } else {\r
271 CountUp = FALSE;\r
272 }\r
273\r
274 TimeStamp = 0;\r
275 Key = 0;\r
276 do {\r
277 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);\r
278 if (Key != 0) {\r
279 for (Index = 0; mTokenList[Index] != NULL; Index++) {\r
280 if (AsciiStriCmp (mTokenList[Index], Token) == 0) {\r
281 Delta = CountUp?(Stop - Start):(Start - Stop);\r
282 TimeStamp += Delta;\r
283 Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);\r
284 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"%6a %6ld ms\n", Token, Milliseconds);\r
285 SerialPortWrite ((UINT8 *) Buffer, CharCount);\r
286 break;\r
287 }\r
288 }\r
289 }\r
290 } while (Key != 0);\r
291\r
292 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));\r
293 SerialPortWrite ((UINT8 *) Buffer, CharCount);\r
294}\r
295\r
c0b2e477 296EFI_STATUS\r
297GetGlobalEnvironmentVariable (\r
298 IN CONST CHAR16* VariableName,\r
299 IN VOID* DefaultValue,\r
300 IN OUT UINTN* Size,\r
301 OUT VOID** Value\r
302 )\r
303{\r
304 return GetEnvironmentVariable (VariableName, &gEfiGlobalVariableGuid,\r
305 DefaultValue, Size, Value);\r
306}\r
307\r
1e57a462 308EFI_STATUS\r
309GetEnvironmentVariable (\r
310 IN CONST CHAR16* VariableName,\r
c0b2e477 311 IN EFI_GUID* VendorGuid,\r
1e57a462 312 IN VOID* DefaultValue,\r
313 IN OUT UINTN* Size,\r
314 OUT VOID** Value\r
315 )\r
316{\r
317 EFI_STATUS Status;\r
318 UINTN VariableSize;\r
319\r
320 // Try to get the variable size.\r
321 *Value = NULL;\r
322 VariableSize = 0;\r
c0b2e477 323 Status = gRT->GetVariable ((CHAR16 *) VariableName, VendorGuid, NULL, &VariableSize, *Value);\r
1e57a462 324 if (Status == EFI_NOT_FOUND) {\r
325 if ((DefaultValue != NULL) && (Size != NULL) && (*Size != 0)) {\r
326 // If the environment variable does not exist yet then set it with the default value\r
327 Status = gRT->SetVariable (\r
328 (CHAR16*)VariableName,\r
c0b2e477 329 VendorGuid,\r
1e57a462 330 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
331 *Size,\r
332 DefaultValue\r
333 );\r
334 *Value = DefaultValue;\r
335 } else {\r
336 return EFI_NOT_FOUND;\r
337 }\r
338 } else if (Status == EFI_BUFFER_TOO_SMALL) {\r
339 // Get the environment variable value\r
340 *Value = AllocatePool (VariableSize);\r
341 if (*Value == NULL) {\r
342 return EFI_OUT_OF_RESOURCES;\r
343 }\r
344\r
c0b2e477 345 Status = gRT->GetVariable ((CHAR16 *)VariableName, VendorGuid, NULL, &VariableSize, *Value);\r
1e57a462 346 if (EFI_ERROR (Status)) {\r
347 FreePool(*Value);\r
348 return EFI_INVALID_PARAMETER;\r
349 }\r
350\r
351 if (Size) {\r
352 *Size = VariableSize;\r
353 }\r
354 } else {\r
355 *Value = DefaultValue;\r
356 return Status;\r
357 }\r
358\r
359 return EFI_SUCCESS;\r
360}\r