]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/DxeHstiLib/HstiDxe.c
3f4d8eb79c728e21c3e8fd9fe644509b9c786365
[mirror_edk2.git] / MdePkg / Library / DxeHstiLib / HstiDxe.c
1 /** @file
2
3 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5
6 **/
7
8 #include "HstiDxe.h"
9
10 /**
11 Find HSTI table in AIP protocol, and return the data.
12 This API will return the HSTI table with indicated Role and ImplementationID,
13 NULL ImplementationID means to find the first HSTI table with indicated Role.
14
15 @param Role Role of HSTI data.
16 @param ImplementationID ImplementationID of HSTI data.
17 NULL means find the first one match Role.
18 @param HstiData HSTI data. This buffer is allocated by callee, and it
19 is the responsibility of the caller to free it after
20 using it.
21 @param HstiSize HSTI size
22
23 @return Aip The AIP protocol having this HSTI.
24 @return NULL There is not HSTI table with the Role and ImplementationID published in system.
25 **/
26 VOID *
27 InternalHstiFindAip (
28 IN UINT32 Role,
29 IN CHAR16 *ImplementationID OPTIONAL,
30 OUT VOID **HstiData OPTIONAL,
31 OUT UINTN *HstiSize OPTIONAL
32 )
33 {
34 EFI_STATUS Status;
35 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
36 UINTN NoHandles;
37 EFI_HANDLE *Handles;
38 UINTN Index;
39 EFI_GUID *InfoTypesBuffer;
40 UINTN InfoTypesBufferCount;
41 UINTN InfoTypesIndex;
42 EFI_ADAPTER_INFORMATION_PROTOCOL *AipCandidate;
43 VOID *InformationBlock;
44 UINTN InformationBlockSize;
45 ADAPTER_INFO_PLATFORM_SECURITY *Hsti;
46
47 Status = gBS->LocateHandleBuffer (
48 ByProtocol,
49 &gEfiAdapterInformationProtocolGuid,
50 NULL,
51 &NoHandles,
52 &Handles
53 );
54 if (EFI_ERROR (Status)) {
55 return NULL;
56 }
57
58 Hsti = NULL;
59 Aip = NULL;
60 InformationBlock = NULL;
61 InformationBlockSize = 0;
62 for (Index = 0; Index < NoHandles; Index++) {
63 Status = gBS->HandleProtocol (
64 Handles[Index],
65 &gEfiAdapterInformationProtocolGuid,
66 (VOID **)&Aip
67 );
68 if (EFI_ERROR (Status)) {
69 continue;
70 }
71
72 //
73 // Check AIP
74 //
75 Status = Aip->GetSupportedTypes (
76 Aip,
77 &InfoTypesBuffer,
78 &InfoTypesBufferCount
79 );
80 if (EFI_ERROR (Status) || (InfoTypesBuffer == NULL) || (InfoTypesBufferCount == 0)) {
81 continue;
82 }
83
84 AipCandidate = NULL;
85 for (InfoTypesIndex = 0; InfoTypesIndex < InfoTypesBufferCount; InfoTypesIndex++) {
86 if (CompareGuid (&InfoTypesBuffer[InfoTypesIndex], &gAdapterInfoPlatformSecurityGuid)) {
87 AipCandidate = Aip;
88 break;
89 }
90 }
91 FreePool (InfoTypesBuffer);
92
93 if (AipCandidate == NULL) {
94 continue;
95 }
96
97 //
98 // Check HSTI Role
99 //
100 Aip = AipCandidate;
101 Status = Aip->GetInformation (
102 Aip,
103 &gAdapterInfoPlatformSecurityGuid,
104 &InformationBlock,
105 &InformationBlockSize
106 );
107 if (EFI_ERROR (Status)) {
108 continue;
109 }
110
111 Hsti = InformationBlock;
112 if ((Hsti->Role == Role) &&
113 ((ImplementationID == NULL) || (StrCmp (ImplementationID, Hsti->ImplementationID) == 0))) {
114 break;
115 } else {
116 Hsti = NULL;
117 FreePool (InformationBlock);
118 continue;
119 }
120 }
121 FreePool (Handles);
122
123 if (Hsti == NULL) {
124 return NULL;
125 }
126
127 if (HstiData != NULL) {
128 *HstiData = InformationBlock;
129 }
130 if (HstiSize != NULL) {
131 *HstiSize = InformationBlockSize;
132 }
133 return Aip;
134 }
135
136 /**
137 Return if input HSTI data follows HSTI specification.
138
139 @param HstiData HSTI data
140 @param HstiSize HSTI size
141
142 @retval TRUE HSTI data follows HSTI specification.
143 @retval FALSE HSTI data does not follow HSTI specification.
144 **/
145 BOOLEAN
146 InternalHstiIsValidTable (
147 IN VOID *HstiData,
148 IN UINTN HstiSize
149 )
150 {
151 ADAPTER_INFO_PLATFORM_SECURITY *Hsti;
152 UINTN Index;
153 CHAR16 *ErrorString;
154 CHAR16 ErrorChar;
155 UINTN ErrorStringSize;
156 UINTN ErrorStringLength;
157
158 Hsti = HstiData;
159
160 //
161 // basic check for header
162 //
163 if (HstiData == NULL) {
164 DEBUG ((DEBUG_ERROR, "HstiData == NULL\n"));
165 return FALSE;
166 }
167 if (HstiSize < sizeof(ADAPTER_INFO_PLATFORM_SECURITY)) {
168 DEBUG ((DEBUG_ERROR, "HstiSize < sizeof(ADAPTER_INFO_PLATFORM_SECURITY)\n"));
169 return FALSE;
170 }
171 if (((HstiSize - sizeof(ADAPTER_INFO_PLATFORM_SECURITY)) / 3) < Hsti->SecurityFeaturesSize) {
172 DEBUG ((DEBUG_ERROR, "((HstiSize - sizeof(ADAPTER_INFO_PLATFORM_SECURITY)) / 3) < SecurityFeaturesSize\n"));
173 return FALSE;
174 }
175
176 //
177 // Check Version
178 //
179 if (Hsti->Version != PLATFORM_SECURITY_VERSION_VNEXTCS) {
180 DEBUG ((DEBUG_ERROR, "Version != PLATFORM_SECURITY_VERSION_VNEXTCS\n"));
181 return FALSE;
182 }
183
184 //
185 // Check Role
186 //
187 if ((Hsti->Role < PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE) ||
188 (Hsti->Role > PLATFORM_SECURITY_ROLE_IMPLEMENTOR_ODM)) {
189 DEBUG ((DEBUG_ERROR, "Role < PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE ||\n"));
190 DEBUG ((DEBUG_ERROR, "Role > PLATFORM_SECURITY_ROLE_IMPLEMENTOR_ODM\n"));
191 return FALSE;
192 }
193
194 //
195 // Check ImplementationID
196 //
197 for (Index = 0; Index < sizeof(Hsti->ImplementationID)/sizeof(Hsti->ImplementationID[0]); Index++) {
198 if (Hsti->ImplementationID[Index] == 0) {
199 break;
200 }
201 }
202 if (Index == sizeof(Hsti->ImplementationID)/sizeof(Hsti->ImplementationID[0])) {
203 DEBUG ((DEBUG_ERROR, "ImplementationID has no NUL CHAR\n"));
204 return FALSE;
205 }
206
207 ErrorStringSize = HstiSize - sizeof(ADAPTER_INFO_PLATFORM_SECURITY) - Hsti->SecurityFeaturesSize * 3;
208 ErrorString = (CHAR16 *)((UINTN)Hsti + sizeof(ADAPTER_INFO_PLATFORM_SECURITY) + Hsti->SecurityFeaturesSize * 3);
209
210 //
211 // basic check for ErrorString
212 //
213 if (ErrorStringSize == 0) {
214 DEBUG ((DEBUG_ERROR, "ErrorStringSize == 0\n"));
215 return FALSE;
216 }
217 if ((ErrorStringSize & BIT0) != 0) {
218 DEBUG ((DEBUG_ERROR, "(ErrorStringSize & BIT0) != 0\n"));
219 return FALSE;
220 }
221
222 //
223 // ErrorString might not be CHAR16 aligned.
224 //
225 CopyMem (&ErrorChar, ErrorString, sizeof(ErrorChar));
226 for (ErrorStringLength = 0; (ErrorChar != 0) && (ErrorStringLength < (ErrorStringSize/2)); ErrorStringLength++) {
227 ErrorString++;
228 CopyMem (&ErrorChar, ErrorString, sizeof(ErrorChar));
229 }
230
231 //
232 // check the length of ErrorString
233 //
234 if (ErrorChar != 0) {
235 DEBUG ((DEBUG_ERROR, "ErrorString has no NUL CHAR\n"));
236 return FALSE;
237 }
238 if (ErrorStringLength == (ErrorStringSize/2)) {
239 DEBUG ((DEBUG_ERROR, "ErrorString Length incorrect\n"));
240 return FALSE;
241 }
242
243 return TRUE;
244 }
245
246 /**
247 Publish HSTI table in AIP protocol.
248
249 One system should have only one PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE.
250
251 If the Role is NOT PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE,
252 SecurityFeaturesRequired field will be ignored.
253
254 @param Hsti HSTI data
255 @param HstiSize HSTI size
256
257 @retval EFI_SUCCESS The HSTI data is published in AIP protocol.
258 @retval EFI_ALREADY_STARTED There is already HSTI table with Role and ImplementationID published in system.
259 @retval EFI_VOLUME_CORRUPTED The input HSTI data does not follow HSTI specification.
260 @retval EFI_OUT_OF_RESOURCES There is not enough system resource to publish HSTI data in AIP protocol.
261 **/
262 EFI_STATUS
263 EFIAPI
264 HstiLibSetTable (
265 IN VOID *Hsti,
266 IN UINTN HstiSize
267 )
268 {
269 EFI_STATUS Status;
270 EFI_HANDLE Handle;
271 HSTI_AIP_PRIVATE_DATA *HstiAip;
272 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
273 UINT32 Role;
274 CHAR16 *ImplementationID;
275 UINT32 SecurityFeaturesSize;
276 UINT8 *SecurityFeaturesRequired;
277
278 if (!InternalHstiIsValidTable (Hsti, HstiSize)) {
279 return EFI_VOLUME_CORRUPTED;
280 }
281
282 Role = ((ADAPTER_INFO_PLATFORM_SECURITY *)Hsti)->Role;
283 ImplementationID = ((ADAPTER_INFO_PLATFORM_SECURITY *)Hsti)->ImplementationID;
284 Aip = InternalHstiFindAip (Role, ImplementationID, NULL, NULL);
285 if (Aip != NULL) {
286 return EFI_ALREADY_STARTED;
287 }
288
289 HstiAip = AllocateZeroPool (sizeof(HSTI_AIP_PRIVATE_DATA));
290 if (HstiAip == NULL) {
291 return EFI_OUT_OF_RESOURCES;
292 }
293 HstiAip->Hsti = AllocateCopyPool (HstiSize, Hsti);
294 if (HstiAip->Hsti == NULL) {
295 FreePool (HstiAip);
296 return EFI_OUT_OF_RESOURCES;
297 }
298 if (Role != PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE) {
299 SecurityFeaturesRequired = (UINT8 *)HstiAip->Hsti + sizeof(ADAPTER_INFO_PLATFORM_SECURITY);
300 SecurityFeaturesSize = ((ADAPTER_INFO_PLATFORM_SECURITY *)Hsti)->SecurityFeaturesSize;
301 ZeroMem (SecurityFeaturesRequired, SecurityFeaturesSize);
302 }
303
304 HstiAip->Signature = HSTI_AIP_PRIVATE_SIGNATURE;
305 CopyMem (&HstiAip->Aip, &mAdapterInformationProtocol, sizeof(EFI_ADAPTER_INFORMATION_PROTOCOL));
306 HstiAip->HstiSize = HstiSize;
307 HstiAip->HstiMaxSize = HstiSize;
308
309 Handle = NULL;
310 Status = gBS->InstallMultipleProtocolInterfaces (
311 &Handle,
312 &gEfiAdapterInformationProtocolGuid,
313 &HstiAip->Aip,
314 NULL
315 );
316 if (EFI_ERROR (Status)) {
317 FreePool (HstiAip->Hsti);
318 FreePool (HstiAip);
319 }
320
321 return Status;
322 }
323
324 /**
325 Search HSTI table in AIP protocol, and return the data.
326 This API will return the HSTI table with indicated Role and ImplementationID,
327 NULL ImplementationID means to find the first HSTI table with indicated Role.
328
329 @param Role Role of HSTI data.
330 @param ImplementationID ImplementationID of HSTI data.
331 NULL means find the first one match Role.
332 @param Hsti HSTI data. This buffer is allocated by callee, and it
333 is the responsibility of the caller to free it after
334 using it.
335 @param HstiSize HSTI size
336
337 @retval EFI_SUCCESS The HSTI data in AIP protocol is returned.
338 @retval EFI_NOT_FOUND There is not HSTI table with the Role and ImplementationID published in system.
339 **/
340 EFI_STATUS
341 EFIAPI
342 HstiLibGetTable (
343 IN UINT32 Role,
344 IN CHAR16 *ImplementationID OPTIONAL,
345 OUT VOID **Hsti,
346 OUT UINTN *HstiSize
347 )
348 {
349 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
350
351 Aip = InternalHstiFindAip (Role, ImplementationID, Hsti, HstiSize);
352 if (Aip == NULL) {
353 return EFI_NOT_FOUND;
354 }
355 return EFI_SUCCESS;
356 }
357
358 /**
359 Record FeaturesVerified in published HSTI table.
360 This API will update the HSTI table with indicated Role and ImplementationID,
361 NULL ImplementationID means to find the first HSTI table with indicated Role.
362
363 @param Role Role of HSTI data.
364 @param ImplementationID ImplementationID of HSTI data.
365 NULL means find the first one match Role.
366 @param ByteIndex Byte index of FeaturesVerified of HSTI data.
367 @param BitMask Bit mask of FeaturesVerified of HSTI data.
368 @param Set TRUE means to set the FeaturesVerified bit.
369 FALSE means to clear the FeaturesVerified bit.
370
371 @retval EFI_SUCCESS The FeaturesVerified of HSTI data updated in AIP protocol.
372 @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system.
373 @retval EFI_UNSUPPORTED The ByteIndex is invalid.
374 **/
375 EFI_STATUS
376 InternalHstiRecordFeaturesVerified (
377 IN UINT32 Role,
378 IN CHAR16 *ImplementationID OPTIONAL,
379 IN UINT32 ByteIndex,
380 IN UINT8 Bit,
381 IN BOOLEAN Set
382 )
383 {
384 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
385 ADAPTER_INFO_PLATFORM_SECURITY *Hsti;
386 UINTN HstiSize;
387 UINT8 *SecurityFeaturesVerified;
388 EFI_STATUS Status;
389
390 Aip = InternalHstiFindAip (Role, ImplementationID, (VOID **)&Hsti, &HstiSize);
391 if (Aip == NULL) {
392 return EFI_NOT_STARTED;
393 }
394
395 if (ByteIndex >= Hsti->SecurityFeaturesSize) {
396 return EFI_UNSUPPORTED;
397 }
398
399 SecurityFeaturesVerified = (UINT8 *)((UINTN)Hsti + sizeof(ADAPTER_INFO_PLATFORM_SECURITY) + Hsti->SecurityFeaturesSize * 2);
400
401 if (Set) {
402 SecurityFeaturesVerified[ByteIndex] = (UINT8)(SecurityFeaturesVerified[ByteIndex] | (Bit));
403 } else {
404 SecurityFeaturesVerified[ByteIndex] = (UINT8)(SecurityFeaturesVerified[ByteIndex] & (~Bit));
405 }
406
407 Status = Aip->SetInformation (
408 Aip,
409 &gAdapterInfoPlatformSecurityGuid,
410 Hsti,
411 HstiSize
412 );
413 FreePool (Hsti);
414 return Status;
415 }
416
417 /**
418 Set FeaturesVerified in published HSTI table.
419 This API will update the HSTI table with indicated Role and ImplementationID,
420 NULL ImplementationID means to find the first HSTI table with indicated Role.
421
422 @param Role Role of HSTI data.
423 @param ImplementationID ImplementationID of HSTI data.
424 NULL means find the first one match Role.
425 @param ByteIndex Byte index of FeaturesVerified of HSTI data.
426 @param BitMask Bit mask of FeaturesVerified of HSTI data.
427
428 @retval EFI_SUCCESS The FeaturesVerified of HSTI data updated in AIP protocol.
429 @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system.
430 @retval EFI_UNSUPPORTED The ByteIndex is invalid.
431 **/
432 EFI_STATUS
433 EFIAPI
434 HstiLibSetFeaturesVerified (
435 IN UINT32 Role,
436 IN CHAR16 *ImplementationID OPTIONAL,
437 IN UINT32 ByteIndex,
438 IN UINT8 BitMask
439 )
440 {
441 return InternalHstiRecordFeaturesVerified (
442 Role,
443 ImplementationID,
444 ByteIndex,
445 BitMask,
446 TRUE
447 );
448 }
449
450 /**
451 Clear FeaturesVerified in published HSTI table.
452 This API will update the HSTI table with indicated Role and ImplementationID,
453 NULL ImplementationID means to find the first HSTI table with indicated Role.
454
455 @param Role Role of HSTI data.
456 @param ImplementationID ImplementationID of HSTI data.
457 NULL means find the first one match Role.
458 @param ByteIndex Byte index of FeaturesVerified of HSTI data.
459 @param BitMask Bit mask of FeaturesVerified of HSTI data.
460
461 @retval EFI_SUCCESS The FeaturesVerified of HSTI data updated in AIP protocol.
462 @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system.
463 @retval EFI_UNSUPPORTED The ByteIndex is invalid.
464 **/
465 EFI_STATUS
466 EFIAPI
467 HstiLibClearFeaturesVerified (
468 IN UINT32 Role,
469 IN CHAR16 *ImplementationID OPTIONAL,
470 IN UINT32 ByteIndex,
471 IN UINT8 BitMask
472 )
473 {
474 return InternalHstiRecordFeaturesVerified (
475 Role,
476 ImplementationID,
477 ByteIndex,
478 BitMask,
479 FALSE
480 );
481 }
482
483 /**
484 Record ErrorString in published HSTI table.
485 This API will update the HSTI table with indicated Role and ImplementationID,
486 NULL ImplementationID means to find the first HSTI table with indicated Role.
487
488 @param Role Role of HSTI data.
489 @param ImplementationID ImplementationID of HSTI data.
490 NULL means find the first one match Role.
491 @param ErrorString ErrorString of HSTI data.
492 @param Append TRUE means to append the ErrorString to HSTI table.
493 FALSE means to set the ErrorString in HSTI table.
494
495 @retval EFI_SUCCESS The ErrorString of HSTI data is published in AIP protocol.
496 @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system.
497 @retval EFI_OUT_OF_RESOURCES There is not enough system resource to update ErrorString.
498 **/
499 EFI_STATUS
500 InternalHstiRecordErrorString (
501 IN UINT32 Role,
502 IN CHAR16 *ImplementationID OPTIONAL,
503 IN CHAR16 *ErrorString,
504 IN BOOLEAN Append
505 )
506 {
507 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
508 ADAPTER_INFO_PLATFORM_SECURITY *Hsti;
509 UINTN HstiSize;
510 UINTN StringSize;
511 VOID *NewHsti;
512 UINTN NewHstiSize;
513 UINTN Offset;
514 EFI_STATUS Status;
515
516 Aip = InternalHstiFindAip (Role, ImplementationID, (VOID **)&Hsti, &HstiSize);
517 if (Aip == NULL) {
518 return EFI_NOT_STARTED;
519 }
520
521 if (Append) {
522 Offset = HstiSize - sizeof(CHAR16);
523 } else {
524 Offset = sizeof(ADAPTER_INFO_PLATFORM_SECURITY) + Hsti->SecurityFeaturesSize * 3;
525 }
526 StringSize = StrSize (ErrorString);
527
528 NewHstiSize = Offset + StringSize;
529 NewHsti = AllocatePool (NewHstiSize);
530 if (NewHsti == NULL) {
531 return EFI_OUT_OF_RESOURCES;
532 }
533
534 CopyMem (NewHsti, Hsti, Offset);
535 CopyMem ((UINT8 *)NewHsti + Offset, ErrorString, StringSize);
536
537 Status = Aip->SetInformation (
538 Aip,
539 &gAdapterInfoPlatformSecurityGuid,
540 NewHsti,
541 NewHstiSize
542 );
543 FreePool (Hsti);
544 FreePool (NewHsti);
545 return Status;
546 }
547
548 /**
549 Append ErrorString in published HSTI table.
550 This API will update the HSTI table with indicated Role and ImplementationID,
551 NULL ImplementationID means to find the first HSTI table with indicated Role.
552
553 @param Role Role of HSTI data.
554 @param ImplementationID ImplementationID of HSTI data.
555 NULL means find the first one match Role.
556 @param ErrorString ErrorString of HSTI data.
557
558 @retval EFI_SUCCESS The ErrorString of HSTI data is updated in AIP protocol.
559 @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system.
560 @retval EFI_OUT_OF_RESOURCES There is not enough system resource to update ErrorString.
561 **/
562 EFI_STATUS
563 EFIAPI
564 HstiLibAppendErrorString (
565 IN UINT32 Role,
566 IN CHAR16 *ImplementationID OPTIONAL,
567 IN CHAR16 *ErrorString
568 )
569 {
570 return InternalHstiRecordErrorString (
571 Role,
572 ImplementationID,
573 ErrorString,
574 TRUE
575 );
576 }
577
578 /**
579 Set a new ErrorString in published HSTI table.
580 This API will update the HSTI table with indicated Role and ImplementationID,
581 NULL ImplementationID means to find the first HSTI table with indicated Role.
582
583 @param Role Role of HSTI data.
584 @param ImplementationID ImplementationID of HSTI data.
585 NULL means find the first one match Role.
586 @param ErrorString ErrorString of HSTI data.
587
588 @retval EFI_SUCCESS The ErrorString of HSTI data is updated in AIP protocol.
589 @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system.
590 @retval EFI_OUT_OF_RESOURCES There is not enough system resource to update ErrorString.
591 **/
592 EFI_STATUS
593 EFIAPI
594 HstiLibSetErrorString (
595 IN UINT32 Role,
596 IN CHAR16 *ImplementationID OPTIONAL,
597 IN CHAR16 *ErrorString
598 )
599 {
600 return InternalHstiRecordErrorString (
601 Role,
602 ImplementationID,
603 ErrorString,
604 FALSE
605 );
606 }