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