3 * Copyright (c) 2011-2013, ARM Limited. All rights reserved.
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
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.
15 #include "BdsInternal.h"
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>
23 STATIC CHAR8
*mTokenList
[] = {
32 ShutdownUefiBootServices (
38 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
41 UINT32 DescriptorVersion
;
49 Status
= gBS
->GetMemoryMap (
56 if (Status
== EFI_BUFFER_TOO_SMALL
) {
58 Pages
= EFI_SIZE_TO_PAGES (MemoryMapSize
) + 1;
59 MemoryMap
= AllocatePages (Pages
);
62 // Get System MemoryMap
64 Status
= gBS
->GetMemoryMap (
73 // Don't do anything between the GetMemoryMap() and ExitBootServices()
74 if (!EFI_ERROR(Status
)) {
75 Status
= gBS
->ExitBootServices (gImageHandle
, MapKey
);
76 if (EFI_ERROR(Status
)) {
77 FreePages (MemoryMap
, Pages
);
82 } while (EFI_ERROR(Status
));
88 Connect all DXE drivers
90 @retval EFI_SUCCESS All drivers have been connected
91 @retval EFI_NOT_FOUND No handles match the search.
92 @retval EFI_OUT_OF_RESOURCES There is not resource pool memory to store the matching results.
96 BdsConnectAllDrivers (
100 UINTN HandleCount
, Index
;
101 EFI_HANDLE
*HandleBuffer
;
105 // Locate all the driver handles
106 Status
= gBS
->LocateHandleBuffer (
113 if (EFI_ERROR (Status
)) {
117 // Connect every handles
118 for (Index
= 0; Index
< HandleCount
; Index
++) {
119 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
122 if (HandleBuffer
!= NULL
) {
123 FreePool (HandleBuffer
);
126 // Check if new handles have been created after the start of the previous handles
127 Status
= gDS
->Dispatch ();
128 } while (!EFI_ERROR(Status
));
135 InsertSystemMemoryResources (
136 LIST_ENTRY
*ResourceList
,
137 EFI_HOB_RESOURCE_DESCRIPTOR
*ResHob
140 BDS_SYSTEM_MEMORY_RESOURCE
*NewResource
;
142 LIST_ENTRY
*NextLink
;
143 LIST_ENTRY AttachedResources
;
144 BDS_SYSTEM_MEMORY_RESOURCE
*Resource
;
145 EFI_PHYSICAL_ADDRESS NewResourceEnd
;
147 if (IsListEmpty (ResourceList
)) {
148 NewResource
= AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE
));
149 NewResource
->PhysicalStart
= ResHob
->PhysicalStart
;
150 NewResource
->ResourceLength
= ResHob
->ResourceLength
;
151 InsertTailList (ResourceList
, &NewResource
->Link
);
155 InitializeListHead (&AttachedResources
);
157 Link
= ResourceList
->ForwardLink
;
158 ASSERT (Link
!= NULL
);
159 while (Link
!= ResourceList
) {
160 Resource
= (BDS_SYSTEM_MEMORY_RESOURCE
*)Link
;
162 // Sanity Check. The resources should not overlapped.
163 ASSERT(!((ResHob
->PhysicalStart
>= Resource
->PhysicalStart
) && (ResHob
->PhysicalStart
< (Resource
->PhysicalStart
+ Resource
->ResourceLength
))));
164 ASSERT(!((ResHob
->PhysicalStart
+ ResHob
->ResourceLength
- 1 >= Resource
->PhysicalStart
) &&
165 ((ResHob
->PhysicalStart
+ ResHob
->ResourceLength
- 1) < (Resource
->PhysicalStart
+ Resource
->ResourceLength
))));
167 // The new resource is attached after this resource descriptor
168 if (ResHob
->PhysicalStart
== Resource
->PhysicalStart
+ Resource
->ResourceLength
) {
169 Resource
->ResourceLength
= Resource
->ResourceLength
+ ResHob
->ResourceLength
;
171 NextLink
= RemoveEntryList (&Resource
->Link
);
172 InsertTailList (&AttachedResources
, &Resource
->Link
);
175 // The new resource is attached before this resource descriptor
176 else if (ResHob
->PhysicalStart
+ ResHob
->ResourceLength
== Resource
->PhysicalStart
) {
177 Resource
->PhysicalStart
= ResHob
->PhysicalStart
;
178 Resource
->ResourceLength
= Resource
->ResourceLength
+ ResHob
->ResourceLength
;
180 NextLink
= RemoveEntryList (&Resource
->Link
);
181 InsertTailList (&AttachedResources
, &Resource
->Link
);
184 Link
= Link
->ForwardLink
;
188 if (!IsListEmpty (&AttachedResources
)) {
189 // See if we can merge the attached resource with other resources
191 NewResource
= (BDS_SYSTEM_MEMORY_RESOURCE
*)GetFirstNode (&AttachedResources
);
192 Link
= RemoveEntryList (&NewResource
->Link
);
193 while (!IsListEmpty (&AttachedResources
)) {
195 Resource
= (BDS_SYSTEM_MEMORY_RESOURCE
*)Link
;
197 // Ensure they overlap each other
199 ((NewResource
->PhysicalStart
>= Resource
->PhysicalStart
) && (NewResource
->PhysicalStart
< (Resource
->PhysicalStart
+ Resource
->ResourceLength
))) ||
200 (((NewResource
->PhysicalStart
+ NewResource
->ResourceLength
) >= Resource
->PhysicalStart
) && ((NewResource
->PhysicalStart
+ NewResource
->ResourceLength
) < (Resource
->PhysicalStart
+ Resource
->ResourceLength
)))
203 NewResourceEnd
= MAX (NewResource
->PhysicalStart
+ NewResource
->ResourceLength
, Resource
->PhysicalStart
+ Resource
->ResourceLength
);
204 NewResource
->PhysicalStart
= MIN (NewResource
->PhysicalStart
, Resource
->PhysicalStart
);
205 NewResource
->ResourceLength
= NewResourceEnd
- NewResource
->PhysicalStart
;
207 Link
= RemoveEntryList (Link
);
210 // None of the Resource of the list is attached to this ResHob. Create a new entry for it
211 NewResource
= AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE
));
212 NewResource
->PhysicalStart
= ResHob
->PhysicalStart
;
213 NewResource
->ResourceLength
= ResHob
->ResourceLength
;
215 InsertTailList (ResourceList
, &NewResource
->Link
);
220 GetSystemMemoryResources (
221 IN LIST_ENTRY
*ResourceList
224 EFI_HOB_RESOURCE_DESCRIPTOR
*ResHob
;
226 InitializeListHead (ResourceList
);
228 // Find the first System Memory Resource Descriptor
229 ResHob
= (EFI_HOB_RESOURCE_DESCRIPTOR
*)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
);
230 while ((ResHob
!= NULL
) && (ResHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
)) {
231 ResHob
= (EFI_HOB_RESOURCE_DESCRIPTOR
*)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
,(VOID
*)((UINTN
)ResHob
+ ResHob
->Header
.HobLength
));
235 if (ResHob
== NULL
) {
236 return EFI_NOT_FOUND
;
238 InsertSystemMemoryResources (ResourceList
, ResHob
);
241 ResHob
= (EFI_HOB_RESOURCE_DESCRIPTOR
*)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
,(VOID
*)((UINTN
)ResHob
+ ResHob
->Header
.HobLength
));
242 while (ResHob
!= NULL
) {
243 if (ResHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) {
244 InsertSystemMemoryResources (ResourceList
, ResHob
);
246 ResHob
= (EFI_HOB_RESOURCE_DESCRIPTOR
*)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
,(VOID
*)((UINTN
)ResHob
+ ResHob
->Header
.HobLength
));
259 CONST CHAR8
*Token
, *Module
;
260 UINT64 Start
, Stop
, TimeStamp
;
261 UINT64 Delta
, TicksPerSecond
, Milliseconds
;
267 TicksPerSecond
= GetPerformanceCounterProperties (&Start
, &Stop
);
277 Key
= GetPerformanceMeasurement (Key
, (CONST VOID
**)&Handle
, &Token
, &Module
, &Start
, &Stop
);
279 for (Index
= 0; mTokenList
[Index
] != NULL
; Index
++) {
280 if (AsciiStriCmp (mTokenList
[Index
], Token
) == 0) {
281 Delta
= CountUp
?(Stop
- Start
):(Start
- Stop
);
283 Milliseconds
= DivU64x64Remainder (MultU64x32 (Delta
, 1000), TicksPerSecond
, NULL
);
284 CharCount
= AsciiSPrint (Buffer
,sizeof (Buffer
),"%6a %6ld ms\n", Token
, Milliseconds
);
285 SerialPortWrite ((UINT8
*) Buffer
, CharCount
);
292 CharCount
= AsciiSPrint (Buffer
,sizeof (Buffer
),"Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp
, 1000), TicksPerSecond
, NULL
));
293 SerialPortWrite ((UINT8
*) Buffer
, CharCount
);
297 GetGlobalEnvironmentVariable (
298 IN CONST CHAR16
* VariableName
,
299 IN VOID
* DefaultValue
,
304 return GetEnvironmentVariable (VariableName
, &gEfiGlobalVariableGuid
,
305 DefaultValue
, Size
, Value
);
309 GetEnvironmentVariable (
310 IN CONST CHAR16
* VariableName
,
311 IN EFI_GUID
* VendorGuid
,
312 IN VOID
* DefaultValue
,
320 // Try to get the variable size.
323 Status
= gRT
->GetVariable ((CHAR16
*) VariableName
, VendorGuid
, NULL
, &VariableSize
, *Value
);
324 if (Status
== EFI_NOT_FOUND
) {
325 if ((DefaultValue
!= NULL
) && (Size
!= NULL
) && (*Size
!= 0)) {
326 // If the environment variable does not exist yet then set it with the default value
327 Status
= gRT
->SetVariable (
328 (CHAR16
*)VariableName
,
330 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
334 *Value
= AllocateCopyPool (*Size
, DefaultValue
);
336 return EFI_NOT_FOUND
;
338 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
339 // Get the environment variable value
340 *Value
= AllocatePool (VariableSize
);
341 if (*Value
== NULL
) {
342 return EFI_OUT_OF_RESOURCES
;
345 Status
= gRT
->GetVariable ((CHAR16
*)VariableName
, VendorGuid
, NULL
, &VariableSize
, *Value
);
346 if (EFI_ERROR (Status
)) {
348 return EFI_INVALID_PARAMETER
;
352 *Size
= VariableSize
;
355 *Value
= AllocateCopyPool (*Size
, DefaultValue
);