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
PrintPerformance(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
InsertSystemMemoryResources(LIST_ENTRY * ResourceList,EFI_HOB_RESOURCE_DESCRIPTOR * ResHob)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
GetSystemMemoryResources(IN LIST_ENTRY * ResourceList)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