TianoCore EDK2 master
Loading...
Searching...
No Matches
DynamicPlatRepo.c
Go to the documentation of this file.
1
15#include <Library/BaseLib.h>
17#include <Library/DebugLib.h>
19
20#include "CmObjectTokenFixer.h"
22#include "TokenGenerator.h"
23
38EFIAPI
40 IN CONST CM_OBJ_DESCRIPTOR *CmObjDesc,
41 IN CM_OBJECT_TOKEN Token,
42 OUT CM_OBJ_NODE **ObjNode
43 )
44{
45 CM_OBJ_NODE *Node;
47
48 if ((CmObjDesc == NULL) || (ObjNode == NULL)) {
49 ASSERT (0);
50 return EFI_INVALID_PARAMETER;
51 }
52
53 Node = AllocateZeroPool (sizeof (CM_OBJ_NODE));
54 if (Node == NULL) {
55 ASSERT (0);
56 return EFI_OUT_OF_RESOURCES;
57 }
58
59 // Initialise the list head.
60 InitializeListHead (&Node->Link);
61 Node->Token = Token;
62 Desc = &Node->CmObjDesc;
63 Desc->ObjectId = CmObjDesc->ObjectId;
64 Desc->Size = CmObjDesc->Size;
65 Desc->Count = CmObjDesc->Count;
66
67 // Allocate and copy the CmObject Data.
68 Desc->Data = AllocateCopyPool (CmObjDesc->Size, CmObjDesc->Data);
69 if (Desc->Data == NULL) {
70 FreePool (Node);
71 ASSERT (0);
72 return EFI_OUT_OF_RESOURCES;
73 }
74
75 *ObjNode = Node;
76 return EFI_SUCCESS;
77}
78
88EFIAPI
90 IN CM_OBJ_NODE *ObjNode
91 )
92{
94
95 if (ObjNode == NULL) {
96 ASSERT (0);
97 return EFI_INVALID_PARAMETER;
98 }
99
100 // Unlink Node
101 RemoveEntryList (&ObjNode->Link);
102
103 Desc = &ObjNode->CmObjDesc;
104 if (Desc->Data != NULL) {
105 FreePool (Desc->Data);
106 }
107
108 FreePool (ObjNode);
109 return EFI_SUCCESS;
110}
111
123EFIAPI
126 IN CONST CM_OBJ_DESCRIPTOR *CmObjDesc,
127 OUT CM_OBJECT_TOKEN *Token OPTIONAL
128 )
129{
130 EFI_STATUS Status;
131 CM_OBJ_NODE *ObjNode;
132 CM_OBJECT_ID ObjId;
133 CM_OBJECT_TOKEN NewToken;
134 LIST_ENTRY *ObjList;
135 EOBJECT_NAMESPACE_ID NamespaceId;
136
137 // The dynamic repository must be able to receive objects.
138 if ((This == NULL) ||
139 (CmObjDesc == NULL) ||
140 (This->RepoState != DynRepoTransient))
141 {
142 ASSERT (0);
143 return EFI_INVALID_PARAMETER;
144 }
145
146 // Check the CmObjDesc:
147 // - only Arm objects and Arch Common objects are supported for now.
148 // - only EArchCommonObjCmRef objects can be added as arrays.
149 if ((CmObjDesc->Size == 0) || (CmObjDesc->Count == 0)) {
150 ASSERT (0);
151 return EFI_INVALID_PARAMETER;
152 }
153
154 ObjId = GET_CM_OBJECT_ID (CmObjDesc->ObjectId);
155 NamespaceId = GET_CM_NAMESPACE_ID (CmObjDesc->ObjectId);
156
157 if (EObjNameSpaceArm == NamespaceId) {
158 if (ObjId >= EArmObjMax) {
159 ASSERT (0);
160 return EFI_INVALID_PARAMETER;
161 }
162
163 ObjList = &This->ArmCmObjList[ObjId];
164 } else if (EObjNameSpaceArchCommon == NamespaceId) {
165 if ((ObjId >= EArchCommonObjMax) ||
166 ((CmObjDesc->Count > 1) && (ObjId != EArchCommonObjCmRef)))
167 {
168 ASSERT (0);
169 return EFI_INVALID_PARAMETER;
170 }
171
172 ObjList = &This->ArchCommonCmObjList[ObjId];
173 } else {
174 ASSERT (0);
175 return EFI_INVALID_PARAMETER;
176 }
177
178 // Generate a token.
179 NewToken = GenerateToken ();
180
181 // Create an ObjNode.
182 Status = AllocCmObjNode (CmObjDesc, NewToken, &ObjNode);
183 if (EFI_ERROR (Status)) {
184 ASSERT (0);
185 return Status;
186 }
187
188 // Fixup self-token if necessary.
189 if (EObjNameSpaceArm == NamespaceId) {
190 Status = FixupCmObjectSelfToken (&ObjNode->CmObjDesc, NewToken);
191 if (EFI_ERROR (Status)) {
192 FreeCmObjNode (ObjNode);
193 ASSERT (0);
194 return Status;
195 }
196 }
197
198 // Add to link list.
199 InsertTailList (ObjList, &ObjNode->Link);
200 This->ObjectCount += 1;
201
202 if (Token != NULL) {
203 *Token = NewToken;
204 }
205
206 return EFI_SUCCESS;
207}
208
223STATIC
225EFIAPI
228 IN EOBJECT_NAMESPACE_ID NamespaceId,
229 IN UINT32 ObjIndex
230 )
231{
232 EFI_STATUS Status;
233 UINTN Count;
234 UINTN Size;
235 UINT32 CmObjId;
236 UINT8 *GroupedData;
237 UINT8 *Data;
238 CM_OBJ_DESCRIPTOR *CmObjDesc;
239 LIST_ENTRY *ListHead;
240 LIST_ENTRY *Link;
241 CM_OBJ_DESCRIPTOR *ObjArray;
242
243 if (This == NULL) {
244 ASSERT (0);
245 return EFI_INVALID_PARAMETER;
246 }
247
248 if (NamespaceId == EObjNameSpaceArm) {
249 if (ObjIndex >= EArmObjMax) {
250 ASSERT (0);
251 return EFI_INVALID_PARAMETER;
252 }
253
254 ListHead = &This->ArmCmObjList[ObjIndex];
255 ObjArray = &This->ArmCmObjArray[ObjIndex];
256 } else if (NamespaceId == EObjNameSpaceArchCommon) {
257 if (ObjIndex >= EArchCommonObjMax) {
258 ASSERT (0);
259 return EFI_INVALID_PARAMETER;
260 }
261
262 ListHead = &This->ArchCommonCmObjList[ObjIndex];
263 ObjArray = &This->ArchCommonCmObjArray[ObjIndex];
264 } else {
265 ASSERT (0);
266 return EFI_INVALID_PARAMETER;
267 }
268
269 Count = 0;
270 Size = 0;
271 CmObjId = CREATE_CM_OBJECT_ID (NamespaceId, ObjIndex);
272 Link = GetFirstNode (ListHead);
273
274 // Compute the total count and size of the CmObj in the list.
275 while (Link != ListHead) {
276 CmObjDesc = &((CM_OBJ_NODE *)Link)->CmObjDesc;
277
278 if (CmObjDesc->ObjectId != CmObjId) {
279 ASSERT (0);
280 return EFI_INVALID_PARAMETER;
281 }
282
283 if ((CmObjDesc->Count != 1) &&
284 ((NamespaceId != EObjNameSpaceArchCommon) ||
285 (ObjIndex != EArchCommonObjCmRef)))
286 {
287 // We expect each descriptor to contain an individual object.
288 // EArchCommonObjCmRef objects are counted as groups, so +1 as well.
289 ASSERT (0);
290 return EFI_INVALID_PARAMETER;
291 }
292
293 Count++;
294 Size += CmObjDesc->Size;
295
296 // Next Link
297 Link = GetNextNode (ListHead, Link);
298 } // while
299
300 if (Count == 0) {
301 // No objects found.
302 return EFI_SUCCESS;
303 }
304
305 GroupedData = AllocateZeroPool (Size);
306 if (GroupedData == NULL) {
307 ASSERT (0);
308 return EFI_OUT_OF_RESOURCES;
309 }
310
311 // Copy the Object Data and add to the TokenMapper.
312 Data = GroupedData;
313 Link = GetFirstNode (ListHead);
314 while (Link != ListHead) {
315 CmObjDesc = &((CM_OBJ_NODE *)Link)->CmObjDesc;
316 CopyMem (Data, CmObjDesc->Data, CmObjDesc->Size);
317
318 // Add the object to the Token Mapper.
319 // Note: The CmObject Data field of objects in the Token Mapper point
320 // to the memory in the GroupedData array.
321 Status = TokenMapperAddObject (
322 &This->TokenMapper,
323 ((CM_OBJ_NODE *)Link)->Token,
324 CmObjDesc->ObjectId,
325 CmObjDesc->Size,
326 Data
327 );
328 if (EFI_ERROR (Status)) {
329 FreePool (GroupedData);
330 return Status;
331 }
332
333 Data += CmObjDesc->Size;
334 Link = GetNextNode (ListHead, Link);
335 } // while
336
337 CmObjDesc = ObjArray;
338 CmObjDesc->ObjectId = CmObjId;
339 CmObjDesc->Size = (UINT32)Size;
340 CmObjDesc->Count = (UINT32)Count;
341 CmObjDesc->Data = GroupedData;
342
343 return Status;
344}
345
362EFIAPI
365 )
366{
367 EFI_STATUS Status;
368 UINTN ObjIndex;
369
370 if ((This == NULL) ||
371 (This->RepoState != DynRepoTransient))
372 {
373 ASSERT (0);
374 return EFI_INVALID_PARAMETER;
375 }
376
377 // Prevent any further objects from being added.
378 This->RepoState = DynRepoFinalized;
379
380 // Initialise the token mapper.
381 Status = TokenMapperInitialise (&This->TokenMapper, This->ObjectCount);
382 if (EFI_ERROR (Status)) {
383 ASSERT (0);
384 return Status;
385 }
386
387 // For each CM_OBJECT_ID:
388 // - Convert the list of nodes to an array
389 // (the array is wrapped in a CmObjDesc).
390 // - Add the Token/CmObj binding to the token mapper.
391 for (ObjIndex = 0; ObjIndex < EArmObjMax; ObjIndex++) {
392 Status = GroupCmObjNodes (This, EObjNameSpaceArm, (UINT32)ObjIndex);
393 if (EFI_ERROR (Status)) {
394 ASSERT (0);
395 goto error_handler;
396 }
397 } // for
398
399 for (ObjIndex = 0; ObjIndex < EArchCommonObjMax; ObjIndex++) {
400 Status = GroupCmObjNodes (This, EObjNameSpaceArchCommon, (UINT32)ObjIndex);
401 if (EFI_ERROR (Status)) {
402 ASSERT (0);
403 goto error_handler;
404 }
405 } // for
406
407 return EFI_SUCCESS;
408
409error_handler:
410 // Free the TokenMapper.
411 // Ignore the returned Status since we already failed.
412 TokenMapperShutdown (&This->TokenMapper);
413 return Status;
414}
415
430EFIAPI
433 IN CM_OBJECT_ID CmObjectId,
434 IN CM_OBJECT_TOKEN Token OPTIONAL,
435 IN OUT CM_OBJ_DESCRIPTOR *CmObjDesc
436 )
437{
438 EFI_STATUS Status;
439 CM_OBJ_DESCRIPTOR *Desc;
440 CM_OBJECT_ID ObjId;
441 EOBJECT_NAMESPACE_ID NamespaceId;
442
443 if ((This == NULL) ||
444 (CmObjDesc == NULL) ||
445 (This->RepoState != DynRepoFinalized))
446 {
447 ASSERT (0);
448 return EFI_INVALID_PARAMETER;
449 }
450
451 NamespaceId = GET_CM_NAMESPACE_ID (CmObjectId);
452 ObjId = GET_CM_OBJECT_ID (CmObjectId);
453
454 if (NamespaceId == EObjNameSpaceArm) {
455 if (ObjId >= EArmObjMax) {
456 ASSERT (0);
457 return EFI_INVALID_PARAMETER;
458 }
459
460 Desc = &This->ArmCmObjArray[ObjId];
461 } else if (NamespaceId == EObjNameSpaceArchCommon) {
462 if ((ObjId >= EArchCommonObjMax) ||
463 ((ObjId == EArchCommonObjCmRef) &&
464 (Token == CM_NULL_TOKEN)))
465 {
466 // EArchCommonObjCmRef object must be requested using a valid token.
467 ASSERT (0);
468 return EFI_INVALID_PARAMETER;
469 }
470
471 Desc = &This->ArchCommonCmObjArray[ObjId];
472 } else {
473 ASSERT (0);
474 return EFI_INVALID_PARAMETER;
475 }
476
477 if (Token != CM_NULL_TOKEN) {
478 // Search in the Token Mapper and return the object.
479 Status = TokenMapperGetObject (
480 &This->TokenMapper,
481 Token,
482 CmObjectId,
483 CmObjDesc
484 );
485 ASSERT_EFI_ERROR (Status);
486 return Status;
487 }
488
489 // Nothing here.
490 if (Desc->Count == 0) {
491 return EFI_NOT_FOUND;
492 } else {
493 // Return the full array.
494 CmObjDesc->ObjectId = Desc->ObjectId;
495 CmObjDesc->Size = Desc->Size;
496 CmObjDesc->Data = Desc->Data;
497 CmObjDesc->Count = Desc->Count;
498 }
499
500 return EFI_SUCCESS;
501}
502
513EFIAPI
516 )
517{
518 UINTN Index;
520
521 if (DynPlatRepo == NULL) {
522 ASSERT (0);
523 return EFI_INVALID_PARAMETER;
524 }
525
527 if (Repo == NULL) {
528 ASSERT (0);
529 return EFI_OUT_OF_RESOURCES;
530 }
531
532 // Initialise the CmObject List.
533 for (Index = 0; Index < EArmObjMax; Index++) {
534 InitializeListHead (&Repo->ArmCmObjList[Index]);
535 }
536
537 for (Index = 0; Index < EArchCommonObjMax; Index++) {
538 InitializeListHead (&Repo->ArchCommonCmObjList[Index]);
539 }
540
541 Repo->ObjectCount = 0;
542 Repo->RepoState = DynRepoTransient;
543
544 *DynPlatRepo = Repo;
545
546 return EFI_SUCCESS;
547}
548
557STATIC
558VOID
559EFIAPI
562 )
563{
564 UINT32 Index;
565 LIST_ENTRY *ListHead;
566 CM_OBJ_DESCRIPTOR *CmObjDesc;
567 VOID *Data;
568
569 ASSERT (DynPlatRepo != NULL);
570
571 // Free the list of objects.
572 for (Index = 0; Index < EArmObjMax; Index++) {
573 // Free all the nodes with this object Id.
574 ListHead = &DynPlatRepo->ArmCmObjList[Index];
575 while (!IsListEmpty (ListHead)) {
576 FreeCmObjNode ((CM_OBJ_NODE *)GetFirstNode (ListHead));
577 } // while
578 } // for
579
580 // Free the arrays.
581 CmObjDesc = DynPlatRepo->ArmCmObjArray;
582 for (Index = 0; Index < EArmObjMax; Index++) {
583 Data = CmObjDesc[Index].Data;
584 if (Data != NULL) {
585 FreePool (Data);
586 }
587 } // for
588}
589
598STATIC
599VOID
600EFIAPI
603 )
604{
605 UINT32 Index;
606 LIST_ENTRY *ListHead;
607 CM_OBJ_DESCRIPTOR *CmObjDesc;
608 VOID *Data;
609
610 ASSERT (DynPlatRepo != NULL);
611
612 // Free the list of objects.
613 for (Index = 0; Index < EArchCommonObjMax; Index++) {
614 // Free all the nodes with this object Id.
615 ListHead = &DynPlatRepo->ArchCommonCmObjList[Index];
616 while (!IsListEmpty (ListHead)) {
617 FreeCmObjNode ((CM_OBJ_NODE *)GetFirstNode (ListHead));
618 } // while
619 } // for
620
621 // Free the arrays.
622 CmObjDesc = DynPlatRepo->ArchCommonCmObjArray;
623 for (Index = 0; Index < EArchCommonObjMax; Index++) {
624 Data = CmObjDesc[Index].Data;
625 if (Data != NULL) {
626 FreePool (Data);
627 }
628 } // for
629}
630
641EFIAPI
644 )
645{
646 EFI_STATUS Status;
647
648 if (DynPlatRepo == NULL) {
649 ASSERT (0);
650 return EFI_INVALID_PARAMETER;
651 }
652
653 DynamicPlatRepoFreeArmObjects (DynPlatRepo);
655
656 // Free the TokenMapper
657 Status = TokenMapperShutdown (&DynPlatRepo->TokenMapper);
658 ASSERT_EFI_ERROR (Status);
659 FreePool (DynPlatRepo);
660 return Status;
661}
UINT64 UINTN
@ EArchCommonObjCmRef
7 - CM Object Reference
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_STATUS EFIAPI FixupCmObjectSelfToken(IN CM_OBJ_DESCRIPTOR *CmObjDesc, IN CM_OBJECT_TOKEN Token)
#define CREATE_CM_OBJECT_ID(NameSpaceId, ObjectId)
#define GET_CM_NAMESPACE_ID(CmObjectId)
#define GET_CM_OBJECT_ID(CmObjectId)
@ EObjNameSpaceArm
ARM Objects Namespace.
@ EObjNameSpaceArchCommon
Arch Common Objects Namespace.
UINT32 CM_OBJECT_ID
enum ObjectNameSpaceID EOBJECT_NAMESPACE_ID
STATIC VOID EFIAPI DynamicPlatRepoFreeArmObjects(IN DYNAMIC_PLATFORM_REPOSITORY_INFO *DynPlatRepo)
STATIC EFI_STATUS EFIAPI FreeCmObjNode(IN CM_OBJ_NODE *ObjNode)
STATIC VOID EFIAPI DynamicPlatRepoFreeArchCommonObjects(IN DYNAMIC_PLATFORM_REPOSITORY_INFO *DynPlatRepo)
EFI_STATUS EFIAPI DynamicPlatRepoGetObject(IN DYNAMIC_PLATFORM_REPOSITORY_INFO *This, IN CM_OBJECT_ID CmObjectId, IN CM_OBJECT_TOKEN Token OPTIONAL, IN OUT CM_OBJ_DESCRIPTOR *CmObjDesc)
EFI_STATUS EFIAPI DynamicPlatRepoShutdown(IN DYNAMIC_PLATFORM_REPOSITORY_INFO *DynPlatRepo)
EFI_STATUS EFIAPI DynPlatRepoAddObject(IN DYNAMIC_PLATFORM_REPOSITORY_INFO *This, IN CONST CM_OBJ_DESCRIPTOR *CmObjDesc, OUT CM_OBJECT_TOKEN *Token OPTIONAL)
STATIC EFI_STATUS EFIAPI AllocCmObjNode(IN CONST CM_OBJ_DESCRIPTOR *CmObjDesc, IN CM_OBJECT_TOKEN Token, OUT CM_OBJ_NODE **ObjNode)
EFI_STATUS EFIAPI DynamicPlatRepoInit(OUT DYNAMIC_PLATFORM_REPOSITORY_INFO **DynPlatRepo)
EFI_STATUS EFIAPI DynamicPlatRepoFinalise(IN DYNAMIC_PLATFORM_REPOSITORY_INFO *This)
STATIC EFI_STATUS EFIAPI GroupCmObjNodes(IN DYNAMIC_PLATFORM_REPOSITORY_INFO *This, IN EOBJECT_NAMESPACE_ID NamespaceId, IN UINT32 ObjIndex)
@ DynRepoFinalized
@ DynRepoTransient
Transient state - CmObjects can be added.
VOID * DYNAMIC_PLATFORM_REPOSITORY_INFO
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
UINTN CM_OBJECT_TOKEN
#define CM_NULL_TOKEN
CM_OBJECT_TOKEN EFIAPI GenerateToken(VOID)
EFI_STATUS EFIAPI TokenMapperInitialise(IN TOKEN_MAPPER *TokenMapper, IN UINTN DescriptorCount)
Definition: TokenMapper.c:161
EFI_STATUS EFIAPI TokenMapperGetObject(IN TOKEN_MAPPER *TokenMapper, IN CM_OBJECT_TOKEN Token, IN CM_OBJECT_ID ObjectId, OUT CM_OBJ_DESCRIPTOR *CmObjDesc)
Definition: TokenMapper.c:97
EFI_STATUS EFIAPI TokenMapperShutdown(IN TOKEN_MAPPER *TokenMapper)
Definition: TokenMapper.c:204
EFI_STATUS EFIAPI TokenMapperAddObject(IN TOKEN_MAPPER *TokenMapper, IN CM_OBJECT_TOKEN Token, IN CM_OBJECT_ID ObjectId, IN UINT32 Size, IN VOID *Data)
Definition: TokenMapper.c:35
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
VOID * Data
Pointer to the described Object or Object List.
UINT32 Size
Size of the described Object or Object List.
UINT32 Count
Count of objects in the list.
CM_OBJECT_ID ObjectId
Object Id.
CM_OBJ_DESCRIPTOR CmObjDesc
CM_OBJECT_TOKEN Token
Token associated with the CmObjDesc.
LIST_ENTRY Link
This must be the first field in this structure.