1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: See COPYING.ARM in the top level directory
3c2c66affSColin Finck * PROJECT: ReactOS UEFI Boot Library
4c2c66affSColin Finck * FILE: boot/environ/lib/misc/util.c
5c2c66affSColin Finck * PURPOSE: Boot Library Utility Functions
6c2c66affSColin Finck * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck /* INCLUDES ******************************************************************/
10c2c66affSColin Finck
11c2c66affSColin Finck #include "bl.h"
12c2c66affSColin Finck
13c2c66affSColin Finck /* DATA VARIABLES ************************************************************/
14c2c66affSColin Finck
15c2c66affSColin Finck PRSDT UtlRsdt;
16c2c66affSColin Finck PXSDT UtlXsdt;
17c2c66affSColin Finck
18c2c66affSColin Finck PVOID UtlMcContext;
19c2c66affSColin Finck PVOID UtlMcDisplayMessageRoutine;
20c2c66affSColin Finck PVOID UtlMcUpdateMessageRoutine;
21c2c66affSColin Finck
22c2c66affSColin Finck PVOID UtlProgressRoutine;
23c2c66affSColin Finck PVOID UtlProgressContext;
24c2c66affSColin Finck PVOID UtlProgressInfoRoutine;
25c2c66affSColin Finck ULONG UtlProgressGranularity;
26c2c66affSColin Finck ULONG UtlCurrentPercentComplete;
27c2c66affSColin Finck ULONG UtlNextUpdatePercentage;
28c2c66affSColin Finck BOOLEAN UtlProgressNeedsInfoUpdate;
29c2c66affSColin Finck PVOID UtlProgressInfo;
30c2c66affSColin Finck
31c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
32c2c66affSColin Finck
33c2c66affSColin Finck NTSTATUS
BlUtlGetAcpiTable(_Out_ PVOID * TableAddress,_In_ ULONG Signature)34c2c66affSColin Finck BlUtlGetAcpiTable (
35c2c66affSColin Finck _Out_ PVOID* TableAddress,
36c2c66affSColin Finck _In_ ULONG Signature
37c2c66affSColin Finck )
38c2c66affSColin Finck {
39c2c66affSColin Finck ULONG i, TableCount, HeaderLength;
40c2c66affSColin Finck NTSTATUS Status;
41c2c66affSColin Finck PRSDT Rsdt;
42c2c66affSColin Finck PXSDT Xsdt;
43c2c66affSColin Finck PHYSICAL_ADDRESS PhysicalAddress;
44c2c66affSColin Finck PDESCRIPTION_HEADER Header;
45c2c66affSColin Finck
46c2c66affSColin Finck Header = 0;
47c2c66affSColin Finck
48c2c66affSColin Finck /* Make sure there's an output parameter */
49c2c66affSColin Finck if (!TableAddress)
50c2c66affSColin Finck {
51c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
52c2c66affSColin Finck }
53c2c66affSColin Finck
54c2c66affSColin Finck /* Get the currently known RSDT and XSDT */
55c2c66affSColin Finck Rsdt = (PRSDT)UtlRsdt;
56c2c66affSColin Finck Xsdt = (PXSDT)UtlXsdt;
57c2c66affSColin Finck
58c2c66affSColin Finck /* Is there an RSDT? */
59c2c66affSColin Finck if (!Rsdt)
60c2c66affSColin Finck {
61c2c66affSColin Finck /* No -- is there an XSDT? */
62c2c66affSColin Finck if (!Xsdt)
63c2c66affSColin Finck {
64c2c66affSColin Finck /* No. Look up the RSDT */
65c2c66affSColin Finck Status = EfipGetRsdt(&PhysicalAddress);
66c2c66affSColin Finck if (!NT_SUCCESS(Status))
67c2c66affSColin Finck {
68c2c66affSColin Finck EfiPrintf(L"no rsdp found\r\n");
69c2c66affSColin Finck return Status;
70c2c66affSColin Finck }
71c2c66affSColin Finck
72c2c66affSColin Finck /* Map the header */
73c2c66affSColin Finck Status = BlMmMapPhysicalAddressEx((PVOID)&Header,
74c2c66affSColin Finck 0,
75c2c66affSColin Finck sizeof(*Header),
76c2c66affSColin Finck PhysicalAddress);
77c2c66affSColin Finck if (!NT_SUCCESS(Status))
78c2c66affSColin Finck {
79c2c66affSColin Finck return Status;
80c2c66affSColin Finck }
81c2c66affSColin Finck
82c2c66affSColin Finck /* Unmap the header */
83c2c66affSColin Finck BlMmUnmapVirtualAddressEx(Header, sizeof(*Header));
84c2c66affSColin Finck
85c2c66affSColin Finck /* Map the whole table */
86c2c66affSColin Finck Status = BlMmMapPhysicalAddressEx((PVOID)&Header,
87c2c66affSColin Finck 0,
88c2c66affSColin Finck Header->Length,
89c2c66affSColin Finck PhysicalAddress);
90c2c66affSColin Finck if (!NT_SUCCESS(Status))
91c2c66affSColin Finck {
92c2c66affSColin Finck return Status;
93c2c66affSColin Finck }
94c2c66affSColin Finck
95c2c66affSColin Finck /* Check if its an XSDT or an RSDT */
96c2c66affSColin Finck if (Header->Signature == XSDT_SIGNATURE)
97c2c66affSColin Finck {
98c2c66affSColin Finck /* It's an XSDT */
99c2c66affSColin Finck Xsdt = (PXSDT)Header;
100c2c66affSColin Finck UtlXsdt = Xsdt;
101c2c66affSColin Finck }
102c2c66affSColin Finck else
103c2c66affSColin Finck {
104c2c66affSColin Finck /* It's an RSDT */
105c2c66affSColin Finck Rsdt = (PRSDT)Header;
106c2c66affSColin Finck UtlRsdt = Rsdt;
107c2c66affSColin Finck }
108c2c66affSColin Finck }
109c2c66affSColin Finck }
110c2c66affSColin Finck
111c2c66affSColin Finck /* OK, so do we have an XSDT after all? */
112c2c66affSColin Finck if (Xsdt)
113c2c66affSColin Finck {
114c2c66affSColin Finck /* Yes... how big is it? */
115c2c66affSColin Finck HeaderLength = Xsdt->Header.Length;
116c2c66affSColin Finck if (HeaderLength >= sizeof(*Header))
117c2c66affSColin Finck {
118c2c66affSColin Finck HeaderLength = sizeof(*Header);
119c2c66affSColin Finck }
120c2c66affSColin Finck
121c2c66affSColin Finck /* Based on that, how many tables are there? */
122c2c66affSColin Finck TableCount = (Xsdt->Header.Length - HeaderLength) / sizeof(PHYSICAL_ADDRESS);
123c2c66affSColin Finck }
124c2c66affSColin Finck else
125c2c66affSColin Finck {
126c2c66affSColin Finck /* Nope, we have an RSDT. How big is it? */
127c2c66affSColin Finck HeaderLength = Rsdt->Header.Length;
128c2c66affSColin Finck if (HeaderLength >= sizeof(*Header))
129c2c66affSColin Finck {
130c2c66affSColin Finck HeaderLength = sizeof(*Header);
131c2c66affSColin Finck }
132c2c66affSColin Finck
133c2c66affSColin Finck /* Based on that, how many tables are there? */
134c2c66affSColin Finck TableCount = (Rsdt->Header.Length - HeaderLength) / sizeof(ULONG);
135c2c66affSColin Finck }
136c2c66affSColin Finck
137c2c66affSColin Finck /* Loop through the ACPI tables */
138c2c66affSColin Finck for (i = 0; i < TableCount; i++)
139c2c66affSColin Finck {
140c2c66affSColin Finck /* For an XSDT, read the 64-bit address directly */
141c2c66affSColin Finck if (Xsdt)
142c2c66affSColin Finck {
143c2c66affSColin Finck PhysicalAddress = Xsdt->Tables[i];
144c2c66affSColin Finck }
145c2c66affSColin Finck else
146c2c66affSColin Finck {
147c2c66affSColin Finck /* For RSDT, cast it */
148c2c66affSColin Finck PhysicalAddress.QuadPart = Rsdt->Tables[i];
149c2c66affSColin Finck }
150c2c66affSColin Finck
151c2c66affSColin Finck /* Map the header */
152c2c66affSColin Finck Status = BlMmMapPhysicalAddressEx((PVOID)&Header,
153c2c66affSColin Finck 0,
154c2c66affSColin Finck sizeof(*Header),
155c2c66affSColin Finck PhysicalAddress);
156c2c66affSColin Finck if (!NT_SUCCESS(Status))
157c2c66affSColin Finck {
158c2c66affSColin Finck return Status;
159c2c66affSColin Finck }
160c2c66affSColin Finck
161c2c66affSColin Finck /* Is it the right one? */
162c2c66affSColin Finck if (Header->Signature == Signature)
163c2c66affSColin Finck {
164c2c66affSColin Finck /* Unmap the header */
165c2c66affSColin Finck BlMmUnmapVirtualAddressEx(Header, sizeof(*Header));
166c2c66affSColin Finck
167c2c66affSColin Finck /* Map the whole table */
168c2c66affSColin Finck return BlMmMapPhysicalAddressEx(TableAddress,
169c2c66affSColin Finck 0,
170c2c66affSColin Finck Header->Length,
171c2c66affSColin Finck PhysicalAddress);
172c2c66affSColin Finck }
173c2c66affSColin Finck }
174c2c66affSColin Finck
175c2c66affSColin Finck /* Requested table does not exist */
176c2c66affSColin Finck return STATUS_NOT_FOUND;
177c2c66affSColin Finck }
178c2c66affSColin Finck
179c2c66affSColin Finck
180c2c66affSColin Finck VOID
BlUtlUpdateProgress(_In_ ULONG Percentage,_Out_opt_ PBOOLEAN Completed)181c2c66affSColin Finck BlUtlUpdateProgress (
182c2c66affSColin Finck _In_ ULONG Percentage,
183c2c66affSColin Finck _Out_opt_ PBOOLEAN Completed
184c2c66affSColin Finck )
185c2c66affSColin Finck {
186c2c66affSColin Finck if (UtlProgressRoutine)
187c2c66affSColin Finck {
188c2c66affSColin Finck EfiPrintf(L"Unimplemented\r\n");
189c2c66affSColin Finck }
190c2c66affSColin Finck else if (*Completed)
191c2c66affSColin Finck {
192c2c66affSColin Finck *Completed = TRUE;
193c2c66affSColin Finck }
194c2c66affSColin Finck }
195c2c66affSColin Finck
196c2c66affSColin Finck NTSTATUS
BlUtlInitialize(VOID)197c2c66affSColin Finck BlUtlInitialize (
198c2c66affSColin Finck VOID
199c2c66affSColin Finck )
200c2c66affSColin Finck {
201c2c66affSColin Finck UtlRsdt = 0;
202c2c66affSColin Finck UtlXsdt = 0;
203c2c66affSColin Finck
204c2c66affSColin Finck UtlMcContext = 0;
205c2c66affSColin Finck UtlMcDisplayMessageRoutine = 0;
206c2c66affSColin Finck UtlMcUpdateMessageRoutine = 0;
207c2c66affSColin Finck
208c2c66affSColin Finck UtlProgressRoutine = 0;
209c2c66affSColin Finck UtlProgressContext = 0;
210c2c66affSColin Finck UtlProgressInfoRoutine = 0;
211c2c66affSColin Finck UtlProgressGranularity = 0;
212c2c66affSColin Finck UtlCurrentPercentComplete = 0;
213c2c66affSColin Finck UtlNextUpdatePercentage = 0;
214c2c66affSColin Finck UtlProgressNeedsInfoUpdate = 0;
215c2c66affSColin Finck UtlProgressInfo = 0;
216c2c66affSColin Finck
217c2c66affSColin Finck return STATUS_SUCCESS;
218c2c66affSColin Finck }
219c2c66affSColin Finck
220c2c66affSColin Finck VOID
BmUpdateProgressInfo(_In_ PVOID Unknown,_In_ PWCHAR ProgressInfo)221c2c66affSColin Finck BmUpdateProgressInfo (
222c2c66affSColin Finck _In_ PVOID Unknown,
223c2c66affSColin Finck _In_ PWCHAR ProgressInfo
224c2c66affSColin Finck )
225c2c66affSColin Finck {
226c2c66affSColin Finck EfiPrintf(L"Progress Info: %s\r\n", ProgressInfo);
227c2c66affSColin Finck }
228c2c66affSColin Finck
229c2c66affSColin Finck VOID
BmUpdateProgress(_In_ PVOID Unknown,_In_ ULONG Percent,_Out_ PBOOLEAN Completed)230c2c66affSColin Finck BmUpdateProgress (
231c2c66affSColin Finck _In_ PVOID Unknown,
232c2c66affSColin Finck _In_ ULONG Percent,
233c2c66affSColin Finck _Out_ PBOOLEAN Completed
234c2c66affSColin Finck )
235c2c66affSColin Finck {
236c2c66affSColin Finck EfiPrintf(L"Progress: %d\r\n", Percent);
237c2c66affSColin Finck if (Completed)
238c2c66affSColin Finck {
239c2c66affSColin Finck *Completed = TRUE;
240c2c66affSColin Finck }
241c2c66affSColin Finck }
242c2c66affSColin Finck
243c2c66affSColin Finck NTSTATUS
BlUtlRegisterProgressRoutine(VOID)244c2c66affSColin Finck BlUtlRegisterProgressRoutine (
245c2c66affSColin Finck VOID
246c2c66affSColin Finck )
247c2c66affSColin Finck {
248c2c66affSColin Finck /* One shouldn't already exist */
249c2c66affSColin Finck if (UtlProgressRoutine)
250c2c66affSColin Finck {
251c2c66affSColin Finck return STATUS_UNSUCCESSFUL;
252c2c66affSColin Finck }
253c2c66affSColin Finck
254c2c66affSColin Finck /* Set the routine, and no context */
255c2c66affSColin Finck UtlProgressRoutine = BmUpdateProgress;
256c2c66affSColin Finck UtlProgressContext = NULL;
257c2c66affSColin Finck
258c2c66affSColin Finck /* Progress increases by one */
259c2c66affSColin Finck UtlProgressGranularity = 1;
260c2c66affSColin Finck
261c2c66affSColin Finck /* Set progress to zero for now */
262c2c66affSColin Finck UtlCurrentPercentComplete = 0;
263c2c66affSColin Finck UtlNextUpdatePercentage = 0;
264c2c66affSColin Finck
265c2c66affSColin Finck /* Set the info routine if there is one */
266c2c66affSColin Finck UtlProgressInfoRoutine = BmUpdateProgressInfo;
267c2c66affSColin Finck
268c2c66affSColin Finck /* All good */
269c2c66affSColin Finck return STATUS_SUCCESS;
270c2c66affSColin Finck }
271c2c66affSColin Finck
272c2c66affSColin Finck PVOID
BlTblFindEntry(_In_ PVOID * Table,_In_ ULONG Count,_Out_ PULONG EntryIndex,_In_ PBL_TBL_LOOKUP_ROUTINE Callback,_In_ PVOID Argument1,_In_ PVOID Argument2,_In_ PVOID Argument3,_In_ PVOID Argument4)273c2c66affSColin Finck BlTblFindEntry (
274c2c66affSColin Finck _In_ PVOID *Table,
275c2c66affSColin Finck _In_ ULONG Count,
276c2c66affSColin Finck _Out_ PULONG EntryIndex,
277c2c66affSColin Finck _In_ PBL_TBL_LOOKUP_ROUTINE Callback,
278c2c66affSColin Finck _In_ PVOID Argument1,
279c2c66affSColin Finck _In_ PVOID Argument2,
280c2c66affSColin Finck _In_ PVOID Argument3,
281c2c66affSColin Finck _In_ PVOID Argument4
282c2c66affSColin Finck )
283c2c66affSColin Finck {
284c2c66affSColin Finck PVOID Entry = NULL;
285c2c66affSColin Finck ULONG Index;
286c2c66affSColin Finck BOOLEAN Result;
287c2c66affSColin Finck
288c2c66affSColin Finck /* Check for invalid parameters */
289c2c66affSColin Finck if (!(Table) || !(EntryIndex))
290c2c66affSColin Finck {
291c2c66affSColin Finck return Entry;
292c2c66affSColin Finck }
293c2c66affSColin Finck
294c2c66affSColin Finck /* Loop each entry in the table */
295c2c66affSColin Finck for (Index = 0; Index < Count; Index++)
296c2c66affSColin Finck {
297c2c66affSColin Finck /* Check if this entry is filled out */
298c2c66affSColin Finck if (Table[Index])
299c2c66affSColin Finck {
300c2c66affSColin Finck /* Call the comparison function */
301c2c66affSColin Finck Result = Callback(Table[Index],
302c2c66affSColin Finck Argument1,
303c2c66affSColin Finck Argument2,
304c2c66affSColin Finck Argument3,
305c2c66affSColin Finck Argument4);
306c2c66affSColin Finck if (Result)
307c2c66affSColin Finck {
308c2c66affSColin Finck /* Entry found return it */
309c2c66affSColin Finck *EntryIndex = Index;
310c2c66affSColin Finck Entry = Table[Index];
311c2c66affSColin Finck break;
312c2c66affSColin Finck }
313c2c66affSColin Finck }
314c2c66affSColin Finck }
315c2c66affSColin Finck
316c2c66affSColin Finck /* Return the entry that was (or wasn't) found */
317c2c66affSColin Finck return Entry;
318c2c66affSColin Finck }
319c2c66affSColin Finck
320c2c66affSColin Finck NTSTATUS
BlTblSetEntry(_Inout_ PVOID ** Table,_Inout_ PULONG Count,_In_ PVOID Entry,_Out_ PULONG EntryIndex,_In_ PBL_TBL_SET_ROUTINE Callback)321c2c66affSColin Finck BlTblSetEntry (
322c2c66affSColin Finck _Inout_ PVOID** Table,
323c2c66affSColin Finck _Inout_ PULONG Count,
324c2c66affSColin Finck _In_ PVOID Entry,
325c2c66affSColin Finck _Out_ PULONG EntryIndex,
326c2c66affSColin Finck _In_ PBL_TBL_SET_ROUTINE Callback
327c2c66affSColin Finck )
328c2c66affSColin Finck {
329c2c66affSColin Finck ULONG NewCount;
330c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS;
331c2c66affSColin Finck ULONG Index = 0;
332c2c66affSColin Finck PVOID* NewTable;
333c2c66affSColin Finck
334c2c66affSColin Finck /* Make sure all the parameters were specified */
335c2c66affSColin Finck if (!(Table) || !(*Table) || !(Count) || !(Callback))
336c2c66affSColin Finck {
337c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
338c2c66affSColin Finck }
339c2c66affSColin Finck
340c2c66affSColin Finck /* Read the current table */
341c2c66affSColin Finck NewTable = *Table;
342c2c66affSColin Finck NewCount = *Count;
343c2c66affSColin Finck
344c2c66affSColin Finck /* Iterate over it */
345c2c66affSColin Finck while (Index < NewCount)
346c2c66affSColin Finck {
347c2c66affSColin Finck /* Look for a free index */
348c2c66affSColin Finck if (!NewTable[Index])
349c2c66affSColin Finck {
350c2c66affSColin Finck goto SetIndex;
351c2c66affSColin Finck }
352c2c66affSColin Finck
353c2c66affSColin Finck /* No free index yet, keep going */
354c2c66affSColin Finck ++Index;
355c2c66affSColin Finck }
356c2c66affSColin Finck
357c2c66affSColin Finck /* No free index was found, try to purge some entries */
358c2c66affSColin Finck Index = 0;
359c2c66affSColin Finck while (Index < NewCount)
360c2c66affSColin Finck {
361c2c66affSColin Finck /* Call each purge callback, trying to make space */
362c2c66affSColin Finck Status = Callback(NewTable[Index]);
363c2c66affSColin Finck if (NT_SUCCESS(Status))
364c2c66affSColin Finck {
365c2c66affSColin Finck /* We should have this slot available now */
366c2c66affSColin Finck goto SetIndex;
367c2c66affSColin Finck }
368c2c66affSColin Finck
369c2c66affSColin Finck /* Keep trying to purge more */
370c2c66affSColin Finck ++Index;
371c2c66affSColin Finck }
372c2c66affSColin Finck
373c2c66affSColin Finck /* Double the table */
374c2c66affSColin Finck NewTable = BlMmAllocateHeap(2 * sizeof(PVOID) * NewCount);
375c2c66affSColin Finck if (!NewTable)
376c2c66affSColin Finck {
377c2c66affSColin Finck return STATUS_NO_MEMORY;
378c2c66affSColin Finck }
379c2c66affSColin Finck
380c2c66affSColin Finck /* Clear the new table, and copy the old entries */
381c2c66affSColin Finck RtlZeroMemory(&NewTable[NewCount], sizeof(PVOID) * NewCount);
382c2c66affSColin Finck RtlCopyMemory(NewTable, *Table, sizeof(PVOID) * NewCount);
383c2c66affSColin Finck
384c2c66affSColin Finck /* Free the old table */
385c2c66affSColin Finck BlMmFreeHeap(*Table);
386c2c66affSColin Finck
387c2c66affSColin Finck /* Return the new table and count */
388c2c66affSColin Finck *Count = 2 * NewCount;
389c2c66affSColin Finck *Table = NewTable;
390c2c66affSColin Finck
391c2c66affSColin Finck SetIndex:
392c2c66affSColin Finck /* Set the index and return */
393c2c66affSColin Finck NewTable[Index] = Entry;
394c2c66affSColin Finck *EntryIndex = Index;
395c2c66affSColin Finck return Status;
396c2c66affSColin Finck }
397c2c66affSColin Finck
398c2c66affSColin Finck NTSTATUS
BlTblMap(_In_ PVOID * Table,_In_ ULONG Count,_In_ PBL_TBL_MAP_ROUTINE MapCallback)399c2c66affSColin Finck BlTblMap (
400c2c66affSColin Finck _In_ PVOID *Table,
401c2c66affSColin Finck _In_ ULONG Count,
402c2c66affSColin Finck _In_ PBL_TBL_MAP_ROUTINE MapCallback
403c2c66affSColin Finck )
404c2c66affSColin Finck {
405c2c66affSColin Finck NTSTATUS Status, LocalStatus;
406c2c66affSColin Finck PVOID Entry;
407c2c66affSColin Finck ULONG Index;
408c2c66affSColin Finck
409c2c66affSColin Finck /* Bail out if there's no table */
410c2c66affSColin Finck if (!Table)
411c2c66affSColin Finck {
412c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
413c2c66affSColin Finck }
414c2c66affSColin Finck
415c2c66affSColin Finck /* Assume success and loop each index */
416c2c66affSColin Finck Status = STATUS_SUCCESS;
417c2c66affSColin Finck for (Index = 0; Index < Count; Index++)
418c2c66affSColin Finck {
419c2c66affSColin Finck /* See if an entry exists at this index */
420c2c66affSColin Finck Entry = Table[Index];
421c2c66affSColin Finck if (Entry)
422c2c66affSColin Finck {
423c2c66affSColin Finck /* Call the map routine for this entry */
424c2c66affSColin Finck LocalStatus = MapCallback(Entry, Index);
425c2c66affSColin Finck if (!NT_SUCCESS(LocalStatus))
426c2c66affSColin Finck {
427c2c66affSColin Finck /* Propagate failure only */
428c2c66affSColin Finck Status = LocalStatus;
429c2c66affSColin Finck }
430c2c66affSColin Finck }
431c2c66affSColin Finck }
432c2c66affSColin Finck
433c2c66affSColin Finck /* Return status to caller */
434c2c66affSColin Finck return Status;
435c2c66affSColin Finck }
436c2c66affSColin Finck
437c2c66affSColin Finck ULONG HtTableSize;
438c2c66affSColin Finck PBL_HASH_TABLE* HtTableArray;
439c2c66affSColin Finck ULONG HtTableEntries;
440c2c66affSColin Finck
441c2c66affSColin Finck ULONG
DefaultHashFunction(_In_ PBL_HASH_ENTRY Entry,_In_ ULONG TableSize)442c2c66affSColin Finck DefaultHashFunction (
443c2c66affSColin Finck _In_ PBL_HASH_ENTRY Entry,
444c2c66affSColin Finck _In_ ULONG TableSize
445c2c66affSColin Finck )
446c2c66affSColin Finck {
447c2c66affSColin Finck PUCHAR Value;
448c2c66affSColin Finck ULONG KeyHash, i;
449c2c66affSColin Finck
450c2c66affSColin Finck /* Check if the value is a pointer, or embedded inline */
451c2c66affSColin Finck Value = (Entry->Flags & BL_HT_VALUE_IS_INLINE) ? Entry->Value : (PUCHAR)&Entry->Value;
452c2c66affSColin Finck
453c2c66affSColin Finck /* Iterate over each byte, and sum it */
454c2c66affSColin Finck for (i = 0, KeyHash = 0; i < Entry->Size; i++)
455c2c66affSColin Finck {
456c2c66affSColin Finck KeyHash += Value[i++];
457c2c66affSColin Finck }
458c2c66affSColin Finck
459c2c66affSColin Finck /* Modulo the number of buckets */
460c2c66affSColin Finck return KeyHash % TableSize;
461c2c66affSColin Finck }
462c2c66affSColin Finck
463c2c66affSColin Finck BOOLEAN
HtpCompareKeys(_In_ PBL_HASH_ENTRY Entry1,_In_ PBL_HASH_ENTRY Entry2)464c2c66affSColin Finck HtpCompareKeys (
465c2c66affSColin Finck _In_ PBL_HASH_ENTRY Entry1,
466c2c66affSColin Finck _In_ PBL_HASH_ENTRY Entry2
467c2c66affSColin Finck )
468c2c66affSColin Finck {
469c2c66affSColin Finck ULONG Flags;
470c2c66affSColin Finck BOOLEAN ValueMatch;
471c2c66affSColin Finck
472c2c66affSColin Finck /* Check if the flags or sizes are not matching */
473c2c66affSColin Finck Flags = Entry1->Flags;
474c2c66affSColin Finck if ((Entry1->Size != Entry2->Size) || (Flags != Entry2->Flags))
475c2c66affSColin Finck {
476c2c66affSColin Finck ValueMatch = FALSE;
477c2c66affSColin Finck }
478c2c66affSColin Finck else if (Flags & BL_HT_VALUE_IS_INLINE)
479c2c66affSColin Finck {
480c2c66affSColin Finck /* Check if this is an in-line value, compare it */
481c2c66affSColin Finck ValueMatch = Entry1->Value == Entry2->Value;
482c2c66affSColin Finck }
483c2c66affSColin Finck else
484c2c66affSColin Finck {
485c2c66affSColin Finck /* This is a pointer value, compare it */
486c2c66affSColin Finck ValueMatch = (RtlCompareMemory(Entry1->Value, Entry2->Value, Entry1->Size) ==
487c2c66affSColin Finck Entry1->Size);
488c2c66affSColin Finck }
489c2c66affSColin Finck
490c2c66affSColin Finck /* Return if it matched */
491c2c66affSColin Finck return ValueMatch;
492c2c66affSColin Finck }
493c2c66affSColin Finck
494c2c66affSColin Finck NTSTATUS
TblDoNotPurgeEntry(_In_ PVOID Entry)495c2c66affSColin Finck TblDoNotPurgeEntry (
496c2c66affSColin Finck _In_ PVOID Entry
497c2c66affSColin Finck )
498c2c66affSColin Finck {
499c2c66affSColin Finck /* Never purge this entry */
500c2c66affSColin Finck return STATUS_UNSUCCESSFUL;
501c2c66affSColin Finck }
502c2c66affSColin Finck
503c2c66affSColin Finck NTSTATUS
BlHtCreate(_In_ ULONG Size,_In_ PBL_HASH_TABLE_HASH_FUNCTION HashFunction,_In_ PBL_HASH_TABLE_COMPARE_FUNCTION CompareFunction,_Out_ PULONG Id)504c2c66affSColin Finck BlHtCreate (
505c2c66affSColin Finck _In_ ULONG Size,
506c2c66affSColin Finck _In_ PBL_HASH_TABLE_HASH_FUNCTION HashFunction,
507c2c66affSColin Finck _In_ PBL_HASH_TABLE_COMPARE_FUNCTION CompareFunction,
508c2c66affSColin Finck _Out_ PULONG Id
509c2c66affSColin Finck )
510c2c66affSColin Finck {
511c2c66affSColin Finck NTSTATUS Status;
512c2c66affSColin Finck PBL_HASH_TABLE HashTable;
513c2c66affSColin Finck ULONG i;
514c2c66affSColin Finck
515c2c66affSColin Finck /* Assume failure */
516c2c66affSColin Finck HashTable = NULL;
517c2c66affSColin Finck
518c2c66affSColin Finck /* Can't create a table with no ID */
519c2c66affSColin Finck if (!Id)
520c2c66affSColin Finck {
521c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
522c2c66affSColin Finck }
523c2c66affSColin Finck
524c2c66affSColin Finck /* Check if we don't already have a hash table table */
525c2c66affSColin Finck if (!HtTableSize)
526c2c66affSColin Finck {
527c2c66affSColin Finck /* Allocate it and zero it out */
528c2c66affSColin Finck HtTableSize = 4;
529c2c66affSColin Finck HtTableArray = BlMmAllocateHeap(HtTableSize * sizeof(PVOID));
530c2c66affSColin Finck if (!HtTableArray)
531c2c66affSColin Finck {
532c2c66affSColin Finck Status = STATUS_NO_MEMORY;
533c2c66affSColin Finck goto Quickie;
534c2c66affSColin Finck }
535c2c66affSColin Finck RtlZeroMemory(HtTableArray, HtTableSize * sizeof(PVOID));
536c2c66affSColin Finck HtTableEntries = 0;
537c2c66affSColin Finck }
538c2c66affSColin Finck
539c2c66affSColin Finck /* Allocate the hash table */
540c2c66affSColin Finck HashTable = BlMmAllocateHeap(sizeof(*HashTable));
541c2c66affSColin Finck if (!HashTable)
542c2c66affSColin Finck {
543c2c66affSColin Finck Status = STATUS_NO_MEMORY;
544c2c66affSColin Finck goto Quickie;
545c2c66affSColin Finck }
546c2c66affSColin Finck
547c2c66affSColin Finck /* Fill it out */
548c2c66affSColin Finck HashTable->HashFunction = HashFunction ? HashFunction : DefaultHashFunction;
549c2c66affSColin Finck HashTable->CompareFunction = CompareFunction ? CompareFunction : HtpCompareKeys;
550c2c66affSColin Finck HashTable->Size = Size ? Size : 13;
551c2c66affSColin Finck
552c2c66affSColin Finck /* Allocate the hash links, one for each bucket */
553c2c66affSColin Finck HashTable->HashLinks = BlMmAllocateHeap(sizeof(LIST_ENTRY) * HashTable->Size);
554c2c66affSColin Finck if (!HashTable->HashLinks)
555c2c66affSColin Finck {
556c2c66affSColin Finck Status = STATUS_NO_MEMORY;
557c2c66affSColin Finck goto Quickie;
558c2c66affSColin Finck }
559c2c66affSColin Finck
560c2c66affSColin Finck /* Initialize the hash links */
561c2c66affSColin Finck for (i = 0; i < HashTable->Size; i++)
562c2c66affSColin Finck {
563c2c66affSColin Finck InitializeListHead(&HashTable->HashLinks[i]);
564c2c66affSColin Finck }
565c2c66affSColin Finck
566c2c66affSColin Finck /* Save us in the table of hash tables */
567c2c66affSColin Finck Status = BlTblSetEntry((PVOID**)&HtTableArray,
568c2c66affSColin Finck &Size,
569c2c66affSColin Finck HashTable,
570c2c66affSColin Finck Id,
571c2c66affSColin Finck TblDoNotPurgeEntry);
572c2c66affSColin Finck if (NT_SUCCESS(Status))
573c2c66affSColin Finck {
574c2c66affSColin Finck /* One more -- we're done */
575c2c66affSColin Finck ++HtTableEntries;
576c2c66affSColin Finck return Status;
577c2c66affSColin Finck }
578c2c66affSColin Finck
579c2c66affSColin Finck Quickie:
580c2c66affSColin Finck /* Check if we just allocated the table array now */
581c2c66affSColin Finck if (!(HtTableEntries) && (HtTableArray))
582c2c66affSColin Finck {
583c2c66affSColin Finck /* Free it */
584c2c66affSColin Finck BlMmFreeHeap(HtTableArray);
585c2c66affSColin Finck HtTableArray = NULL;
586c2c66affSColin Finck HtTableSize = 0;
587c2c66affSColin Finck }
588c2c66affSColin Finck
589c2c66affSColin Finck /* Check if we allocated a hash table*/
590c2c66affSColin Finck if (HashTable)
591c2c66affSColin Finck {
592c2c66affSColin Finck /* With links? */
593c2c66affSColin Finck if (HashTable->HashLinks)
594c2c66affSColin Finck {
595c2c66affSColin Finck /* Free them */
596c2c66affSColin Finck BlMmFreeHeap(HashTable->HashLinks);
597c2c66affSColin Finck }
598c2c66affSColin Finck
599c2c66affSColin Finck /* Free the table*/
600c2c66affSColin Finck BlMmFreeHeap(HashTable);
601c2c66affSColin Finck }
602c2c66affSColin Finck
603c2c66affSColin Finck /* We're done */
604c2c66affSColin Finck return Status;
605c2c66affSColin Finck }
606c2c66affSColin Finck
607c2c66affSColin Finck NTSTATUS
BlHtLookup(_In_ ULONG TableId,_In_ PBL_HASH_ENTRY Entry,_Out_opt_ PBL_HASH_VALUE * Value)608c2c66affSColin Finck BlHtLookup (
609c2c66affSColin Finck _In_ ULONG TableId,
610c2c66affSColin Finck _In_ PBL_HASH_ENTRY Entry,
611c2c66affSColin Finck _Out_opt_ PBL_HASH_VALUE *Value
612c2c66affSColin Finck )
613c2c66affSColin Finck {
614c2c66affSColin Finck PBL_HASH_TABLE HashTable;
615c2c66affSColin Finck ULONG HashValue;
616c2c66affSColin Finck NTSTATUS Status;
617c2c66affSColin Finck PLIST_ENTRY HashLinkHead, HashLink;
618c2c66affSColin Finck PBL_HASH_NODE HashNode;
619c2c66affSColin Finck
620c2c66affSColin Finck /* Check if the table ID is invalid, or we have no entry, or it's malformed */
621c2c66affSColin Finck if ((HtTableSize <= TableId) ||
622c2c66affSColin Finck !(Entry) ||
623c2c66affSColin Finck ((Entry->Flags & BL_HT_VALUE_IS_INLINE) && (Entry->Size != sizeof(ULONG))))
624c2c66affSColin Finck {
625c2c66affSColin Finck /* Fail */
626c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER;
627c2c66affSColin Finck }
628c2c66affSColin Finck else
629c2c66affSColin Finck {
630c2c66affSColin Finck /* Otherwise, get the hash table for this index */
631c2c66affSColin Finck HashTable = HtTableArray[TableId];
632c2c66affSColin Finck
633c2c66affSColin Finck /* Get the hash bucket */
634c2c66affSColin Finck HashValue = HashTable->HashFunction(Entry, HashTable->Size);
635c2c66affSColin Finck
636c2c66affSColin Finck /* Start iterating each entry in the bucket, assuming failure */
637c2c66affSColin Finck Status = STATUS_NOT_FOUND;
638c2c66affSColin Finck HashLinkHead = &HashTable->HashLinks[HashValue];
639c2c66affSColin Finck HashLink = HashLinkHead->Flink;
640c2c66affSColin Finck while (HashLink != HashLinkHead)
641c2c66affSColin Finck {
642c2c66affSColin Finck /* Get a node in this bucket, and compare the value */
643c2c66affSColin Finck HashNode = CONTAINING_RECORD(HashLink, BL_HASH_NODE, ListEntry);
644c2c66affSColin Finck if (HashTable->CompareFunction(&HashNode->Entry, Entry))
645c2c66affSColin Finck {
646c2c66affSColin Finck /* Does the caller want the value? */
647c2c66affSColin Finck if (Value)
648c2c66affSColin Finck {
649c2c66affSColin Finck /* Return it */
650c2c66affSColin Finck *Value = &HashNode->Value;
651c2c66affSColin Finck }
652c2c66affSColin Finck
653c2c66affSColin Finck /* Return success and stop scanning */
654c2c66affSColin Finck Status = STATUS_SUCCESS;
655c2c66affSColin Finck break;
656c2c66affSColin Finck }
657c2c66affSColin Finck
658c2c66affSColin Finck /* Try the next node */
659c2c66affSColin Finck HashLink = HashLink->Flink;
660c2c66affSColin Finck }
661c2c66affSColin Finck }
662c2c66affSColin Finck
663c2c66affSColin Finck /* Return back to the caller */
664c2c66affSColin Finck return Status;
665c2c66affSColin Finck }
666c2c66affSColin Finck
667c2c66affSColin Finck NTSTATUS
BlHtStore(_In_ ULONG TableId,_In_ PBL_HASH_ENTRY Entry,_In_ PVOID Data,_In_ ULONG DataSize)668c2c66affSColin Finck BlHtStore (
669c2c66affSColin Finck _In_ ULONG TableId,
670c2c66affSColin Finck _In_ PBL_HASH_ENTRY Entry,
671c2c66affSColin Finck _In_ PVOID Data,
672c2c66affSColin Finck _In_ ULONG DataSize
673c2c66affSColin Finck )
674c2c66affSColin Finck {
675c2c66affSColin Finck PBL_HASH_NODE HashNode;
676c2c66affSColin Finck NTSTATUS Status;
677c2c66affSColin Finck PLIST_ENTRY HashLinkHead;
678c2c66affSColin Finck PBL_HASH_TABLE HashTable;
679c2c66affSColin Finck
680c2c66affSColin Finck /* Check for invalid table ID, missing arguments, or malformed entry */
681c2c66affSColin Finck if ((HtTableSize <= TableId) ||
682c2c66affSColin Finck !(Entry) ||
683c2c66affSColin Finck !(Data) ||
684c2c66affSColin Finck !(Entry->Size) ||
685c2c66affSColin Finck !(Entry->Value) ||
686c2c66affSColin Finck !(DataSize) ||
687c2c66affSColin Finck ((Entry->Flags & BL_HT_VALUE_IS_INLINE) && (Entry->Size != sizeof(ULONG))))
688c2c66affSColin Finck {
689c2c66affSColin Finck /* Fail the call */
690c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER;
691c2c66affSColin Finck goto Quickie;
692c2c66affSColin Finck }
693c2c66affSColin Finck
694c2c66affSColin Finck /* Get the hash table for this ID */
695c2c66affSColin Finck HashTable = HtTableArray[TableId];
696c2c66affSColin Finck
697c2c66affSColin Finck /* Allocate a hash node */
698c2c66affSColin Finck HashNode = BlMmAllocateHeap(sizeof(*HashNode));
699c2c66affSColin Finck if (!HashNode)
700c2c66affSColin Finck {
701c2c66affSColin Finck Status = STATUS_NO_MEMORY;
702c2c66affSColin Finck goto Quickie;
703c2c66affSColin Finck }
704c2c66affSColin Finck
705c2c66affSColin Finck /* Capture all the data*/
706c2c66affSColin Finck HashNode->Entry.Size = Entry->Size;
707c2c66affSColin Finck HashNode->Entry.Flags = Entry->Flags;
708c2c66affSColin Finck HashNode->Entry.Value = Entry->Value;
709c2c66affSColin Finck HashNode->Value.DataSize = DataSize;
710c2c66affSColin Finck HashNode->Value.Data = Data;
711c2c66affSColin Finck
712c2c66affSColin Finck /* Insert it into the bucket list and return success */
713c2c66affSColin Finck HashLinkHead = &HashTable->HashLinks[HashTable->HashFunction(Entry, HashTable->Size)];
714c2c66affSColin Finck InsertTailList(HashLinkHead, &HashNode->ListEntry);
715c2c66affSColin Finck Status = STATUS_SUCCESS;
716c2c66affSColin Finck
717c2c66affSColin Finck Quickie:
718c2c66affSColin Finck return Status;
719c2c66affSColin Finck }
720c2c66affSColin Finck
721c2c66affSColin Finck NTSTATUS
BlHtDelete(_In_ ULONG TableId,_In_ PBL_HASH_ENTRY Entry)722c2c66affSColin Finck BlHtDelete (
723c2c66affSColin Finck _In_ ULONG TableId,
724c2c66affSColin Finck _In_ PBL_HASH_ENTRY Entry
725c2c66affSColin Finck )
726c2c66affSColin Finck {
727c2c66affSColin Finck PBL_HASH_TABLE HashTable;
728c2c66affSColin Finck ULONG HashValue;
729c2c66affSColin Finck NTSTATUS Status;
730c2c66affSColin Finck PLIST_ENTRY HashLinkHead, HashLink;
731c2c66affSColin Finck PBL_HASH_NODE HashNode;
732c2c66affSColin Finck
733c2c66affSColin Finck /* Check if the table ID is invalid, or we have no entry, or it's malformed */
734c2c66affSColin Finck if ((HtTableSize <= TableId) ||
735c2c66affSColin Finck !(Entry) ||
736c2c66affSColin Finck !(Entry->Size) ||
737c2c66affSColin Finck !(Entry->Value) ||
738c2c66affSColin Finck ((Entry->Flags & BL_HT_VALUE_IS_INLINE) && (Entry->Size != sizeof(ULONG))))
739c2c66affSColin Finck {
740c2c66affSColin Finck /* Fail */
741c2c66affSColin Finck Status = STATUS_INVALID_PARAMETER;
742c2c66affSColin Finck }
743c2c66affSColin Finck else
744c2c66affSColin Finck {
745c2c66affSColin Finck /* Otherwise, get the hash table for this index */
746c2c66affSColin Finck HashTable = HtTableArray[TableId];
747c2c66affSColin Finck
748c2c66affSColin Finck /* Get the hash bucket */
749c2c66affSColin Finck HashValue = HashTable->HashFunction(Entry, HashTable->Size);
750c2c66affSColin Finck
751c2c66affSColin Finck /* Start iterating each entry in the bucket, assuming failure */
752c2c66affSColin Finck Status = STATUS_NOT_FOUND;
753c2c66affSColin Finck HashLinkHead = &HashTable->HashLinks[HashValue];
754c2c66affSColin Finck HashLink = HashLinkHead->Flink;
755c2c66affSColin Finck while (HashLink != HashLinkHead)
756c2c66affSColin Finck {
757c2c66affSColin Finck /* Get a node in this bucket, and compare the value */
758c2c66affSColin Finck HashNode = CONTAINING_RECORD(HashLink, BL_HASH_NODE, ListEntry);
759c2c66affSColin Finck if (HashTable->CompareFunction(&HashNode->Entry, Entry))
760c2c66affSColin Finck {
761c2c66affSColin Finck /* Remove it from the list and free it */
762c2c66affSColin Finck RemoveEntryList(&HashNode->ListEntry);
763c2c66affSColin Finck BlMmFreeHeap(HashNode);
764c2c66affSColin Finck return STATUS_SUCCESS;
765c2c66affSColin Finck }
766c2c66affSColin Finck
767c2c66affSColin Finck /* Try the next node */
768c2c66affSColin Finck HashLink = HashLink->Flink;
769c2c66affSColin Finck }
770c2c66affSColin Finck }
771c2c66affSColin Finck
772c2c66affSColin Finck /* Return back to the caller */
773c2c66affSColin Finck return Status;
774c2c66affSColin Finck }
775c2c66affSColin Finck
776c2c66affSColin Finck ULONG
BlUtlCheckSum(_In_ ULONG PartialSum,_In_ PUCHAR Buffer,_In_ ULONG Length,_In_ ULONG Flags)777c2c66affSColin Finck BlUtlCheckSum (
778c2c66affSColin Finck _In_ ULONG PartialSum,
779c2c66affSColin Finck _In_ PUCHAR Buffer,
780c2c66affSColin Finck _In_ ULONG Length,
781c2c66affSColin Finck _In_ ULONG Flags
782c2c66affSColin Finck )
783c2c66affSColin Finck {
784c2c66affSColin Finck ULONG i;
785c2c66affSColin Finck
786c2c66affSColin Finck if (Flags & BL_UTL_CHECKSUM_UCHAR_BUFFER)
787c2c66affSColin Finck {
788c2c66affSColin Finck EfiPrintf(L"Not supported\r\n");
789c2c66affSColin Finck return 0;
790c2c66affSColin Finck }
791c2c66affSColin Finck else if (Flags & BL_UTL_CHECKSUM_USHORT_BUFFER)
792c2c66affSColin Finck {
793c2c66affSColin Finck PartialSum = (unsigned __int16)PartialSum;
794c2c66affSColin Finck Length &= ~1;
795c2c66affSColin Finck
796c2c66affSColin Finck for (i = 0; i < Length; i += 2)
797c2c66affSColin Finck {
798c2c66affSColin Finck PartialSum += *(unsigned __int16 *)&Buffer[i];
799c2c66affSColin Finck if (Flags & BL_UTL_CHECKSUM_COMPLEMENT)
800c2c66affSColin Finck {
801c2c66affSColin Finck PartialSum = (unsigned __int16)((PartialSum >> 16) + PartialSum);
802c2c66affSColin Finck }
803c2c66affSColin Finck }
804c2c66affSColin Finck
805c2c66affSColin Finck if (i != Length)
806c2c66affSColin Finck {
807c2c66affSColin Finck PartialSum += (unsigned __int8)Buffer[Length];
808c2c66affSColin Finck if (Flags & BL_UTL_CHECKSUM_COMPLEMENT)
809c2c66affSColin Finck {
810c2c66affSColin Finck PartialSum = (unsigned __int16)((PartialSum >> 16) + PartialSum);
811c2c66affSColin Finck }
812c2c66affSColin Finck }
813c2c66affSColin Finck
814c2c66affSColin Finck if (Flags & BL_UTL_CHECKSUM_NEGATE)
815c2c66affSColin Finck {
816c2c66affSColin Finck return ~PartialSum;
817c2c66affSColin Finck }
818c2c66affSColin Finck
819c2c66affSColin Finck PartialSum = (unsigned __int16)PartialSum;
820c2c66affSColin Finck }
821c2c66affSColin Finck else
822c2c66affSColin Finck {
823c2c66affSColin Finck /* Invalid mode */
824c2c66affSColin Finck return 0;
825c2c66affSColin Finck }
826c2c66affSColin Finck
827c2c66affSColin Finck if (Flags & BL_UTL_CHECKSUM_NEGATE)
828c2c66affSColin Finck {
829c2c66affSColin Finck return ~PartialSum;
830c2c66affSColin Finck }
831c2c66affSColin Finck
832c2c66affSColin Finck return PartialSum;
833c2c66affSColin Finck }
834c2c66affSColin Finck
835c2c66affSColin Finck #if defined(_M_IX86) || defined(_M_X64)
836c2c66affSColin Finck BOOLEAN
Archx86IsCpuidSupported(VOID)837c2c66affSColin Finck Archx86IsCpuidSupported (
838c2c66affSColin Finck VOID
839c2c66affSColin Finck )
840c2c66affSColin Finck {
841c2c66affSColin Finck ULONG CallerFlags, Flags;
842c2c66affSColin Finck
843c2c66affSColin Finck /* Read the original flags, and add the CPUID bit */
844c2c66affSColin Finck CallerFlags = __readeflags() ^ 0x200000;
845c2c66affSColin Finck __writeeflags(CallerFlags);
846c2c66affSColin Finck
847c2c66affSColin Finck /* Read our flags now */
848c2c66affSColin Finck Flags = __readeflags();
849c2c66affSColin Finck
850c2c66affSColin Finck /* Check if the bit stuck */
851c2c66affSColin Finck return (((CallerFlags ^ Flags) >> 21) & 1) ^ 1;
852c2c66affSColin Finck }
853c2c66affSColin Finck #endif
854c2c66affSColin Finck
855c2c66affSColin Finck BOOLEAN
BlArchIsCpuIdFunctionSupported(_In_ ULONG Function)856c2c66affSColin Finck BlArchIsCpuIdFunctionSupported (
857c2c66affSColin Finck _In_ ULONG Function
858c2c66affSColin Finck )
859c2c66affSColin Finck {
860c2c66affSColin Finck #if defined(_M_IX86) || defined(_M_X64)
861c2c66affSColin Finck BOOLEAN Supported;
862c2c66affSColin Finck INT CpuInfo[4];
863c2c66affSColin Finck
864c2c66affSColin Finck /* Check if the CPU supports this instruction */
865c2c66affSColin Finck Supported = Archx86IsCpuidSupported();
866c2c66affSColin Finck if (!Supported)
867c2c66affSColin Finck {
868c2c66affSColin Finck return FALSE;
869c2c66affSColin Finck }
870c2c66affSColin Finck
871c2c66affSColin Finck /* Check if it's the extended function */
872c2c66affSColin Finck if (Function >= 0x80000000)
873c2c66affSColin Finck {
874c2c66affSColin Finck /* Check if extended functions are supported */
875c2c66affSColin Finck __cpuid(CpuInfo, 0x80000000);
876c2c66affSColin Finck if ((CpuInfo[0] & 0xFFFFFF00) != 0x80000000)
877c2c66affSColin Finck {
878c2c66affSColin Finck /* Nope */
879c2c66affSColin Finck return FALSE;
880c2c66affSColin Finck }
881c2c66affSColin Finck }
882c2c66affSColin Finck else
883c2c66affSColin Finck {
884c2c66affSColin Finck /* It's a regular function, get the maximum one supported */
885c2c66affSColin Finck __cpuid(CpuInfo, 0);
886c2c66affSColin Finck }
887c2c66affSColin Finck
888c2c66affSColin Finck /* Check if our function is within bounds */
889c2c66affSColin Finck if (Function <= CpuInfo[0])
890c2c66affSColin Finck {
891c2c66affSColin Finck return TRUE;
892c2c66affSColin Finck }
893c2c66affSColin Finck #else
894c2c66affSColin Finck EfiPrintf(L"BlArchIsCpuIdFunctionSupported not implemented for this platform.\r\n");
895c2c66affSColin Finck #endif
896c2c66affSColin Finck
897c2c66affSColin Finck /* Nope */
898c2c66affSColin Finck return FALSE;
899c2c66affSColin Finck }
900c2c66affSColin Finck
901c2c66affSColin Finck ULONGLONG
BlArchGetPerformanceCounter(VOID)902c2c66affSColin Finck BlArchGetPerformanceCounter (
903c2c66affSColin Finck VOID
904c2c66affSColin Finck )
905c2c66affSColin Finck {
906c2c66affSColin Finck #if defined(_M_IX86) || defined(_M_X64)
907478348eaSAlex Ionescu CPU_INFO CpuInfo;
908c2c66affSColin Finck
909c2c66affSColin Finck /* Serialize with CPUID, if it exists */
910c2c66affSColin Finck if (Archx86IsCpuidSupported())
911c2c66affSColin Finck {
912478348eaSAlex Ionescu BlArchCpuId(0, 0, &CpuInfo);
913c2c66affSColin Finck }
914c2c66affSColin Finck
915c2c66affSColin Finck /* Read the TSC */
916c2c66affSColin Finck return __rdtsc();
917c2c66affSColin Finck #else
918c2c66affSColin Finck EfiPrintf(L"BlArchGetPerformanceCounter not implemented for this platform.\r\n");
919c2c66affSColin Finck return 0;
920c2c66affSColin Finck #endif
921c2c66affSColin Finck }
922c2c66affSColin Finck
923c2c66affSColin Finck VOID
BlArchCpuId(_In_ ULONG Function,_In_ ULONG SubFunction,_Out_ PCPU_INFO Result)924c2c66affSColin Finck BlArchCpuId (
925c2c66affSColin Finck _In_ ULONG Function,
926c2c66affSColin Finck _In_ ULONG SubFunction,
927478348eaSAlex Ionescu _Out_ PCPU_INFO Result
928c2c66affSColin Finck )
929c2c66affSColin Finck {
930c2c66affSColin Finck #if defined(_M_IX86) || defined(_M_X64)
931c2c66affSColin Finck /* Use the intrinsic */
932478348eaSAlex Ionescu __cpuidex((INT*)Result->AsUINT32, Function, SubFunction);
933c2c66affSColin Finck #endif
934c2c66affSColin Finck }
935e836d0b5SAlex Ionescu
936e836d0b5SAlex Ionescu CPU_VENDORS
BlArchGetCpuVendor(VOID)937e836d0b5SAlex Ionescu BlArchGetCpuVendor (
938e836d0b5SAlex Ionescu VOID
939e836d0b5SAlex Ionescu )
940e836d0b5SAlex Ionescu {
941478348eaSAlex Ionescu CPU_INFO CpuInfo;
942e836d0b5SAlex Ionescu INT Temp;
943e836d0b5SAlex Ionescu
944e836d0b5SAlex Ionescu /* Get the CPU Vendor */
945478348eaSAlex Ionescu BlArchCpuId(0, 0, &CpuInfo);
946*a380a616SMark Jansen #if defined(_M_IX86) || defined(_M_X64)
947478348eaSAlex Ionescu Temp = CpuInfo.Ecx;
948478348eaSAlex Ionescu CpuInfo.Ecx = CpuInfo.Edx;
949478348eaSAlex Ionescu CpuInfo.Edx = Temp;
950e836d0b5SAlex Ionescu
951e836d0b5SAlex Ionescu /* Check against supported values */
952478348eaSAlex Ionescu if (!strncmp((PCHAR)&CpuInfo.Ebx, "GenuineIntel", 12))
953e836d0b5SAlex Ionescu {
954e836d0b5SAlex Ionescu return CPU_INTEL;
955e836d0b5SAlex Ionescu }
956478348eaSAlex Ionescu if (!strncmp((PCHAR)&CpuInfo.Ebx, "AuthenticAMD", 12))
957e836d0b5SAlex Ionescu {
958e836d0b5SAlex Ionescu return CPU_AMD;
959e836d0b5SAlex Ionescu }
960478348eaSAlex Ionescu if (!strncmp((PCHAR)&CpuInfo.Ebx, "CentaurHauls", 12))
961e836d0b5SAlex Ionescu {
962e836d0b5SAlex Ionescu return CPU_VIA;
963e836d0b5SAlex Ionescu }
9643be40816STimo Kreuzer #ifdef _M_IX86
965478348eaSAlex Ionescu if (!strncmp((PCHAR)&CpuInfo.Ebx, "CyrixInstead", 12))
966e836d0b5SAlex Ionescu {
967e836d0b5SAlex Ionescu return CPU_CYRIX;
968e836d0b5SAlex Ionescu }
969478348eaSAlex Ionescu if (!strncmp((PCHAR)&CpuInfo.Ebx, "GenuineTMx86", 12))
970e836d0b5SAlex Ionescu {
971e836d0b5SAlex Ionescu return CPU_TRANSMETA;
972e836d0b5SAlex Ionescu }
973478348eaSAlex Ionescu if (!strncmp((PCHAR)&CpuInfo.Ebx, "RiseRiseRise", 12))
974e836d0b5SAlex Ionescu {
975e836d0b5SAlex Ionescu return CPU_RISE;
976e836d0b5SAlex Ionescu }
9773be40816STimo Kreuzer #endif // _M_IX86
978*a380a616SMark Jansen #else // defined(_M_IX86) || defined(_M_X64)
979*a380a616SMark Jansen EfiPrintf(L"BlArchGetCpuVendor not implemented for this platform.\r\n");
980*a380a616SMark Jansen #endif
981e836d0b5SAlex Ionescu /* Other */
982e836d0b5SAlex Ionescu return CPU_UNKNOWN;
983e836d0b5SAlex Ionescu }
984