1 /** @file 2 * 3 * Copyright (c) 2011-2015, 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 <PiDxe.h> 16 #include <Library/HobLib.h> 17 #include <Library/TimerLib.h> 18 #include <Library/SerialPortLib.h> 19 20 #include "LinuxLoader.h" 21 22 STATIC CONST CHAR8 *mTokenList[] = { 23 /*"SEC",*/ 24 "PEI", 25 "DXE", 26 "BDS", 27 NULL 28 }; 29 30 VOID 31 PrintPerformance ( 32 VOID 33 ) 34 { 35 UINTN Key; 36 CONST VOID *Handle; 37 CONST CHAR8 *Token, *Module; 38 UINT64 Start, Stop, TimeStamp; 39 UINT64 Delta, TicksPerSecond, Milliseconds; 40 UINTN Index; 41 CHAR8 Buffer[100]; 42 UINTN CharCount; 43 BOOLEAN CountUp; 44 45 TicksPerSecond = GetPerformanceCounterProperties (&Start, &Stop); 46 if (Start < Stop) { 47 CountUp = TRUE; 48 } else { 49 CountUp = FALSE; 50 } 51 52 TimeStamp = 0; 53 Key = 0; 54 do { 55 Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop); 56 if (Key != 0) { 57 for (Index = 0; mTokenList[Index] != NULL; Index++) { 58 if (AsciiStriCmp (mTokenList[Index], Token) == 0) { 59 Delta = CountUp ? (Stop - Start) : (Start - Stop); 60 TimeStamp += Delta; 61 Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL); 62 CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "%6a %6ld ms\n", Token, Milliseconds); 63 SerialPortWrite ((UINT8 *) Buffer, CharCount); 64 break; 65 } 66 } 67 } 68 } while (Key != 0); 69 70 CharCount = AsciiSPrint (Buffer, sizeof (Buffer), "Total Time = %ld ms\n\n", 71 DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL)); 72 SerialPortWrite ((UINT8 *) Buffer, CharCount); 73 } 74 75 STATIC 76 EFI_STATUS 77 InsertSystemMemoryResources ( 78 LIST_ENTRY *ResourceList, 79 EFI_HOB_RESOURCE_DESCRIPTOR *ResHob 80 ) 81 { 82 SYSTEM_MEMORY_RESOURCE *NewResource; 83 LIST_ENTRY *Link; 84 LIST_ENTRY *NextLink; 85 LIST_ENTRY AttachedResources; 86 SYSTEM_MEMORY_RESOURCE *Resource; 87 EFI_PHYSICAL_ADDRESS NewResourceEnd; 88 89 if (IsListEmpty (ResourceList)) { 90 NewResource = AllocateZeroPool (sizeof (SYSTEM_MEMORY_RESOURCE)); 91 NewResource->PhysicalStart = ResHob->PhysicalStart; 92 NewResource->ResourceLength = ResHob->ResourceLength; 93 InsertTailList (ResourceList, &NewResource->Link); 94 return EFI_SUCCESS; 95 } 96 97 InitializeListHead (&AttachedResources); 98 99 Link = ResourceList->ForwardLink; 100 ASSERT (Link != NULL); 101 while (Link != ResourceList) { 102 Resource = (SYSTEM_MEMORY_RESOURCE*)Link; 103 104 // Sanity Check. The resources should not overlapped. 105 ASSERT (!((ResHob->PhysicalStart >= Resource->PhysicalStart) && (ResHob->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength)))); 106 ASSERT (!((ResHob->PhysicalStart + ResHob->ResourceLength - 1 >= Resource->PhysicalStart) && 107 ((ResHob->PhysicalStart + ResHob->ResourceLength - 1) < (Resource->PhysicalStart + Resource->ResourceLength)))); 108 109 // The new resource is attached after this resource descriptor 110 if (ResHob->PhysicalStart == Resource->PhysicalStart + Resource->ResourceLength) { 111 Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength; 112 113 NextLink = RemoveEntryList (&Resource->Link); 114 InsertTailList (&AttachedResources, &Resource->Link); 115 Link = NextLink; 116 } 117 // The new resource is attached before this resource descriptor 118 else if (ResHob->PhysicalStart + ResHob->ResourceLength == Resource->PhysicalStart) { 119 Resource->PhysicalStart = ResHob->PhysicalStart; 120 Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength; 121 122 NextLink = RemoveEntryList (&Resource->Link); 123 InsertTailList (&AttachedResources, &Resource->Link); 124 Link = NextLink; 125 } else { 126 Link = Link->ForwardLink; 127 } 128 } 129 130 if (!IsListEmpty (&AttachedResources)) { 131 // See if we can merge the attached resource with other resources 132 133 NewResource = (SYSTEM_MEMORY_RESOURCE*)GetFirstNode (&AttachedResources); 134 Link = RemoveEntryList (&NewResource->Link); 135 while (!IsListEmpty (&AttachedResources)) { 136 // Merge resources 137 Resource = (SYSTEM_MEMORY_RESOURCE*)Link; 138 139 // Ensure they overlap each other 140 ASSERT ( 141 ((NewResource->PhysicalStart >= Resource->PhysicalStart) && (NewResource->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))) || 142 (((NewResource->PhysicalStart + NewResource->ResourceLength) >= Resource->PhysicalStart) && ((NewResource->PhysicalStart + NewResource->ResourceLength) < (Resource->PhysicalStart + Resource->ResourceLength))) 143 ); 144 145 NewResourceEnd = MAX (NewResource->PhysicalStart + NewResource->ResourceLength, Resource->PhysicalStart + Resource->ResourceLength); 146 NewResource->PhysicalStart = MIN (NewResource->PhysicalStart, Resource->PhysicalStart); 147 NewResource->ResourceLength = NewResourceEnd - NewResource->PhysicalStart; 148 149 Link = RemoveEntryList (Link); 150 } 151 } else { 152 // None of the Resource of the list is attached to this ResHob. Create a new entry for it 153 NewResource = AllocateZeroPool (sizeof (SYSTEM_MEMORY_RESOURCE)); 154 NewResource->PhysicalStart = ResHob->PhysicalStart; 155 NewResource->ResourceLength = ResHob->ResourceLength; 156 } 157 InsertTailList (ResourceList, &NewResource->Link); 158 return EFI_SUCCESS; 159 } 160 161 EFI_STATUS 162 GetSystemMemoryResources ( 163 IN LIST_ENTRY *ResourceList 164 ) 165 { 166 EFI_HOB_RESOURCE_DESCRIPTOR *ResHob; 167 168 InitializeListHead (ResourceList); 169 170 // Find the first System Memory Resource Descriptor 171 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); 172 while ((ResHob != NULL) && (ResHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)) { 173 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength)); 174 } 175 176 // Did not find any 177 if (ResHob == NULL) { 178 return EFI_NOT_FOUND; 179 } else { 180 InsertSystemMemoryResources (ResourceList, ResHob); 181 } 182 183 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength)); 184 while (ResHob != NULL) { 185 if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { 186 InsertSystemMemoryResources (ResourceList, ResHob); 187 } 188 ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, (VOID *)((UINTN)ResHob + ResHob->Header.HobLength)); 189 } 190 191 return EFI_SUCCESS; 192 } 193