VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/Library/HardwareInfoLib/HardwareInfoDxe.c@ 101291

Last change on this file since 101291 was 101291, checked in by vboxsync, 14 months ago

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • Property svn:eol-style set to native
File size: 6.1 KB
Line 
1/*/@file
2 Hardware info parsing functions.
3 Binary data is expected as a consecutive series of header - object pairs.
4 Complete library providing list-like interface to dynamically manipulate
5 hardware info objects and parsing from a generic blob.
6
7 Copyright 2021 - 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10**/
11
12#include <Uefi/UefiBaseType.h>
13#include <Uefi/UefiSpec.h>
14#include <Library/DebugLib.h>
15#include <Library/MemoryAllocationLib.h>
16#include <Library/BaseMemoryLib.h>
17#include <Library/BaseLib.h>
18#include <Library/UefiLib.h>
19
20#include <Library/HardwareInfoLib.h>
21
22EFI_STATUS
23CreateHardwareInfoList (
24 IN UINT8 *Blob,
25 IN UINTN BlobSize,
26 IN HARDWARE_INFO_TYPE TypeFilter,
27 OUT LIST_ENTRY *ListHead
28 )
29{
30 UINT8 *Index;
31 UINT8 *BlobEnd;
32 HARDWARE_INFO *HwComponent;
33
34 if ((Blob == NULL) || (BlobSize <= 0) ||
35 (ListHead == NULL))
36 {
37 return EFI_INVALID_PARAMETER;
38 }
39
40 Index = Blob;
41 BlobEnd = Blob + BlobSize;
42 while (Index < BlobEnd) {
43 HwComponent = AllocateZeroPool (sizeof (HARDWARE_INFO));
44
45 if (HwComponent == NULL) {
46 goto FailedAllocate;
47 }
48
49 HwComponent->Header.Type.Uint64 = *((UINT64 *)Index);
50 Index += sizeof (HwComponent->Header.Type);
51 HwComponent->Header.Size = *((UINT64 *)(Index));
52 Index += sizeof (HwComponent->Header.Size);
53
54 if ((HwComponent->Header.Size > MAX_UINTN) || (Index < Blob) || ((Index + HwComponent->Header.Size) > BlobEnd)) {
55 goto FreeResources;
56 }
57
58 //
59 // Check if optional TypeFilter is set, skip if the current
60 // object is of a different type and release the partially
61 // allocated object
62 //
63 if ((TypeFilter != HardwareInfoTypeUndefined) &&
64 (HwComponent->Header.Type.Value != TypeFilter))
65 {
66 FreePool (HwComponent);
67 Index += HwComponent->Header.Size;
68 continue;
69 }
70
71 HwComponent->Data.Raw = AllocateZeroPool ((UINTN)HwComponent->Header.Size);
72 if (HwComponent->Data.Raw == NULL) {
73 goto FreeResources;
74 }
75
76 CopyMem (HwComponent->Data.Raw, Index, (UINTN)HwComponent->Header.Size);
77 Index += HwComponent->Header.Size;
78
79 InsertTailList (ListHead, &HwComponent->Link);
80 }
81
82 return EFI_SUCCESS;
83
84FreeResources:
85 //
86 // Clean the resources allocated in the incomplete cycle
87 //
88 FreePool (HwComponent);
89
90FailedAllocate:
91 DEBUG ((
92 EFI_D_ERROR,
93 "%a: Failed to allocate memory for hardware info\n",
94 __func__
95 ));
96
97 return EFI_OUT_OF_RESOURCES;
98}
99
100VOID
101FreeHardwareInfoList (
102 IN OUT LIST_ENTRY *ListHead
103 )
104{
105 LIST_ENTRY *CurrentLink;
106 HARDWARE_INFO *HwComponent;
107
108 if (IsListEmpty (ListHead)) {
109 return;
110 }
111
112 CurrentLink = ListHead->ForwardLink;
113 while (CurrentLink != NULL && CurrentLink != ListHead) {
114 HwComponent = HARDWARE_INFO_FROM_LINK (CurrentLink);
115
116 //
117 // Remove item from list before invalidating the pointers
118 //
119 CurrentLink = RemoveEntryList (CurrentLink);
120
121 FreePool (HwComponent->Data.Raw);
122 FreePool (HwComponent);
123 }
124}
125
126/**
127 Validates if the specified Node has a valid data size and is of
128 specified type.
129 The data size can be less or equal to the provided type size to be
130 regarded as valid and thus accessible with the typed pointer.
131
132 For future compatibility the size is allowed to be smaller so that
133 different versions interpret fields differently and, particularly,
134 have smaller data structures. However, it cannot be larger than the
135 type size to avoid accessing memory out of bounds.
136
137 @param[in] Node Hardware Info node to be validated
138 @param[in] TypeSize Size (in bytes) of the data type intended to be
139 used to dereference the data.
140 @retval TRUE Node is valid and can be accessed
141 @retval FALSE Node is not valid
142/*/
143STATIC
144BOOLEAN
145IsHardwareInfoNodeValidByType (
146 IN LIST_ENTRY *ListHead,
147 IN LIST_ENTRY *Link,
148 IN HARDWARE_INFO_TYPE Type,
149 IN UINTN TypeSize
150 )
151{
152 HARDWARE_INFO *HwComponent;
153
154 if (IsNull (ListHead, Link)) {
155 return FALSE;
156 }
157
158 HwComponent = HARDWARE_INFO_FROM_LINK (Link);
159
160 //
161 // Verify if the node type is the specified one and the size of
162 // the data allocated to the node is greater than the size of
163 // the type intended to dereference it in order to avoid access
164 // to memory out of bondaries.
165 //
166 if ((HwComponent->Header.Type.Value == Type) &&
167 (HwComponent->Header.Size >= TypeSize))
168 {
169 return TRUE;
170 }
171
172 return FALSE;
173}
174
175UINTN
176GetHardwareInfoCountByType (
177 IN LIST_ENTRY *ListHead,
178 IN HARDWARE_INFO_TYPE Type,
179 IN UINTN TypeSize
180 )
181{
182 UINTN Count;
183 LIST_ENTRY *Link;
184
185 Count = 0;
186 for (Link = GetFirstHardwareInfoByType (ListHead, Type, TypeSize);
187 !IsNull (ListHead, Link);
188 Link = GetNextHardwareInfoByType (ListHead, Link, Type, TypeSize))
189 {
190 if (IsHardwareInfoNodeValidByType (ListHead, Link, Type, TypeSize)) {
191 Count++;
192 }
193 }
194
195 return Count;
196}
197
198LIST_ENTRY *
199GetFirstHardwareInfoByType (
200 IN LIST_ENTRY *ListHead,
201 IN HARDWARE_INFO_TYPE Type,
202 IN UINTN TypeSize
203 )
204{
205 LIST_ENTRY *Link;
206
207 if (IsListEmpty (ListHead)) {
208 return ListHead;
209 }
210
211 Link = GetFirstNode (ListHead);
212
213 if (IsHardwareInfoNodeValidByType (ListHead, Link, Type, TypeSize)) {
214 return Link;
215 }
216
217 return GetNextHardwareInfoByType (ListHead, Link, Type, TypeSize);
218}
219
220LIST_ENTRY *
221GetNextHardwareInfoByType (
222 IN LIST_ENTRY *ListHead,
223 IN LIST_ENTRY *Node,
224 IN HARDWARE_INFO_TYPE Type,
225 IN UINTN TypeSize
226 )
227{
228 LIST_ENTRY *Link;
229
230 Link = GetNextNode (ListHead, Node);
231
232 while (!IsNull (ListHead, Link)) {
233 if (IsHardwareInfoNodeValidByType (ListHead, Link, Type, TypeSize)) {
234 //
235 // Found a node of specified type and with valid size. Break and
236 // return the found node.
237 //
238 break;
239 }
240
241 Link = GetNextNode (ListHead, Link);
242 }
243
244 return Link;
245}
246
247BOOLEAN
248EndOfHardwareInfoList (
249 IN LIST_ENTRY *ListHead,
250 IN LIST_ENTRY *Node
251 )
252{
253 return IsNull (ListHead, Node);
254}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette