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/HobLib.h>
18 #include <Library/TimerLib.h>
19 #include <Library/PrintLib.h>
20 #include <Library/SerialPortLib.h>
22 STATIC CHAR8
*mTokenList
[] = {
31 ShutdownUefiBootServices (
37 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
40 UINT32 DescriptorVersion
;
48 Status
= gBS
->GetMemoryMap (
55 if (Status
== EFI_BUFFER_TOO_SMALL
) {
57 Pages
= EFI_SIZE_TO_PAGES (MemoryMapSize
) + 1;
58 MemoryMap
= AllocatePages (Pages
);
61 // Get System MemoryMap
63 Status
= gBS
->GetMemoryMap (
72 // Don't do anything between the GetMemoryMap() and ExitBootServices()
73 if (!EFI_ERROR(Status
)) {
74 Status
= gBS
->ExitBootServices (gImageHandle
, MapKey
);
75 if (EFI_ERROR(Status
)) {
76 FreePages (MemoryMap
, Pages
);
81 } while (EFI_ERROR(Status
));
87 Connect all DXE drivers
89 @retval EFI_SUCCESS All drivers have been connected
90 @retval EFI_NOT_FOUND No handles match the search.
91 @retval EFI_OUT_OF_RESOURCES There is not resource pool memory to store the matching results.
95 BdsConnectAllDrivers (
99 UINTN HandleCount
, Index
;
100 EFI_HANDLE
*HandleBuffer
;
104 // Locate all the driver handles
105 Status
= gBS
->LocateHandleBuffer (
112 if (EFI_ERROR (Status
)) {
116 // Connect every handles
117 for (Index
= 0; Index
< HandleCount
; Index
++) {
118 gBS
->ConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
121 if (HandleBuffer
!= NULL
) {
122 FreePool (HandleBuffer
);
125 // Check if new handles have been created after the start of the previous handles
126 Status
= gDS
->Dispatch ();
127 } while (!EFI_ERROR(Status
));
134 InsertSystemMemoryResources (
135 LIST_ENTRY
*ResourceList
,
136 EFI_HOB_RESOURCE_DESCRIPTOR
*ResHob
139 BDS_SYSTEM_MEMORY_RESOURCE
*NewResource
;
141 LIST_ENTRY
*NextLink
;
142 LIST_ENTRY AttachedResources
;
143 BDS_SYSTEM_MEMORY_RESOURCE
*Resource
;
144 EFI_PHYSICAL_ADDRESS NewResourceEnd
;
146 if (IsListEmpty (ResourceList
)) {
147 NewResource
= AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE
));
148 NewResource
->PhysicalStart
= ResHob
->PhysicalStart
;
149 NewResource
->ResourceLength
= ResHob
->ResourceLength
;
150 InsertTailList (ResourceList
, &NewResource
->Link
);
154 InitializeListHead (&AttachedResources
);
156 Link
= ResourceList
->ForwardLink
;
157 ASSERT (Link
!= NULL
);
158 while (Link
!= ResourceList
) {
159 Resource
= (BDS_SYSTEM_MEMORY_RESOURCE
*)Link
;
161 // Sanity Check. The resources should not overlapped.
162 ASSERT(!((ResHob
->PhysicalStart
>= Resource
->PhysicalStart
) && (ResHob
->PhysicalStart
< (Resource
->PhysicalStart
+ Resource
->ResourceLength
))));
163 ASSERT(!((ResHob
->PhysicalStart
+ ResHob
->ResourceLength
- 1 >= Resource
->PhysicalStart
) &&
164 ((ResHob
->PhysicalStart
+ ResHob
->ResourceLength
- 1) < (Resource
->PhysicalStart
+ Resource
->ResourceLength
))));
166 // The new resource is attached after this resource descriptor
167 if (ResHob
->PhysicalStart
== Resource
->PhysicalStart
+ Resource
->ResourceLength
) {
168 Resource
->ResourceLength
= Resource
->ResourceLength
+ ResHob
->ResourceLength
;
170 NextLink
= RemoveEntryList (&Resource
->Link
);
171 InsertTailList (&AttachedResources
, &Resource
->Link
);
174 // The new resource is attached before this resource descriptor
175 else if (ResHob
->PhysicalStart
+ ResHob
->ResourceLength
== Resource
->PhysicalStart
) {
176 Resource
->PhysicalStart
= ResHob
->PhysicalStart
;
177 Resource
->ResourceLength
= Resource
->ResourceLength
+ ResHob
->ResourceLength
;
179 NextLink
= RemoveEntryList (&Resource
->Link
);
180 InsertTailList (&AttachedResources
, &Resource
->Link
);
183 Link
= Link
->ForwardLink
;
187 if (!IsListEmpty (&AttachedResources
)) {
188 // See if we can merge the attached resource with other resources
190 NewResource
= (BDS_SYSTEM_MEMORY_RESOURCE
*)GetFirstNode (&AttachedResources
);
191 Link
= RemoveEntryList (&NewResource
->Link
);
192 while (!IsListEmpty (&AttachedResources
)) {
194 Resource
= (BDS_SYSTEM_MEMORY_RESOURCE
*)Link
;
196 // Ensure they overlap each other
198 ((NewResource
->PhysicalStart
>= Resource
->PhysicalStart
) && (NewResource
->PhysicalStart
< (Resource
->PhysicalStart
+ Resource
->ResourceLength
))) ||
199 (((NewResource
->PhysicalStart
+ NewResource
->ResourceLength
) >= Resource
->PhysicalStart
) && ((NewResource
->PhysicalStart
+ NewResource
->ResourceLength
) < (Resource
->PhysicalStart
+ Resource
->ResourceLength
)))
202 NewResourceEnd
= MAX (NewResource
->PhysicalStart
+ NewResource
->ResourceLength
, Resource
->PhysicalStart
+ Resource
->ResourceLength
);
203 NewResource
->PhysicalStart
= MIN (NewResource
->PhysicalStart
, Resource
->PhysicalStart
);
204 NewResource
->ResourceLength
= NewResourceEnd
- NewResource
->PhysicalStart
;
206 Link
= RemoveEntryList (Link
);
209 // None of the Resource of the list is attached to this ResHob. Create a new entry for it
210 NewResource
= AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE
));
211 NewResource
->PhysicalStart
= ResHob
->PhysicalStart
;
212 NewResource
->ResourceLength
= ResHob
->ResourceLength
;
214 InsertTailList (ResourceList
, &NewResource
->Link
);
219 GetSystemMemoryResources (
220 IN LIST_ENTRY
*ResourceList
223 EFI_HOB_RESOURCE_DESCRIPTOR
*ResHob
;
225 InitializeListHead (ResourceList
);
227 // Find the first System Memory Resource Descriptor
228 ResHob
= (EFI_HOB_RESOURCE_DESCRIPTOR
*)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
);
229 while ((ResHob
!= NULL
) && (ResHob
->ResourceType
!= EFI_RESOURCE_SYSTEM_MEMORY
)) {
230 ResHob
= (EFI_HOB_RESOURCE_DESCRIPTOR
*)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
,(VOID
*)((UINTN
)ResHob
+ ResHob
->Header
.HobLength
));
234 if (ResHob
== NULL
) {
235 return EFI_NOT_FOUND
;
237 InsertSystemMemoryResources (ResourceList
, ResHob
);
240 ResHob
= (EFI_HOB_RESOURCE_DESCRIPTOR
*)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
,(VOID
*)((UINTN
)ResHob
+ ResHob
->Header
.HobLength
));
241 while (ResHob
!= NULL
) {
242 if (ResHob
->ResourceType
== EFI_RESOURCE_SYSTEM_MEMORY
) {
243 InsertSystemMemoryResources (ResourceList
, ResHob
);
245 ResHob
= (EFI_HOB_RESOURCE_DESCRIPTOR
*)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
,(VOID
*)((UINTN
)ResHob
+ ResHob
->Header
.HobLength
));
258 CONST CHAR8
*Token
, *Module
;
259 UINT64 Start
, Stop
, TimeStamp
;
260 UINT64 Delta
, TicksPerSecond
, Milliseconds
;
266 TicksPerSecond
= GetPerformanceCounterProperties (&Start
, &Stop
);
276 Key
= GetPerformanceMeasurement (Key
, (CONST VOID
**)&Handle
, &Token
, &Module
, &Start
, &Stop
);
278 for (Index
= 0; mTokenList
[Index
] != NULL
; Index
++) {
279 if (AsciiStriCmp (mTokenList
[Index
], Token
) == 0) {
280 Delta
= CountUp
?(Stop
- Start
):(Start
- Stop
);
282 Milliseconds
= DivU64x64Remainder (MultU64x32 (Delta
, 1000), TicksPerSecond
, NULL
);
283 CharCount
= AsciiSPrint (Buffer
,sizeof (Buffer
),"%6a %6ld ms\n", Token
, Milliseconds
);
284 SerialPortWrite ((UINT8
*) Buffer
, CharCount
);
291 CharCount
= AsciiSPrint (Buffer
,sizeof (Buffer
),"Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp
, 1000), TicksPerSecond
, NULL
));
292 SerialPortWrite ((UINT8
*) Buffer
, CharCount
);
296 GetGlobalEnvironmentVariable (
297 IN CONST CHAR16
* VariableName
,
298 IN VOID
* DefaultValue
,
303 return GetEnvironmentVariable (VariableName
, &gEfiGlobalVariableGuid
,
304 DefaultValue
, Size
, Value
);
308 GetEnvironmentVariable (
309 IN CONST CHAR16
* VariableName
,
310 IN EFI_GUID
* VendorGuid
,
311 IN VOID
* DefaultValue
,
319 // Try to get the variable size.
322 Status
= gRT
->GetVariable ((CHAR16
*) VariableName
, VendorGuid
, NULL
, &VariableSize
, *Value
);
323 if (Status
== EFI_NOT_FOUND
) {
324 if ((DefaultValue
!= NULL
) && (Size
!= NULL
) && (*Size
!= 0)) {
325 // If the environment variable does not exist yet then set it with the default value
326 Status
= gRT
->SetVariable (
327 (CHAR16
*)VariableName
,
329 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
333 *Value
= AllocateCopyPool (*Size
, DefaultValue
);
335 return EFI_NOT_FOUND
;
337 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
338 // Get the environment variable value
339 *Value
= AllocatePool (VariableSize
);
340 if (*Value
== NULL
) {
341 return EFI_OUT_OF_RESOURCES
;
344 Status
= gRT
->GetVariable ((CHAR16
*)VariableName
, VendorGuid
, NULL
, &VariableSize
, *Value
);
345 if (EFI_ERROR (Status
)) {
347 return EFI_INVALID_PARAMETER
;
351 *Size
= VariableSize
;
354 *Value
= AllocateCopyPool (*Size
, DefaultValue
);