Initial import.
[mirror_edk2.git] / EdkModulePkg / Universal / PCD / Dxe / Service.c
CommitLineData
878ddf1f 1/** @file\r
2Private functions used by PCD DXE driver.s\r
3\r
4Copyright (c) 2006, Intel Corporation\r
5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13\r
14Module Name: Service.c\r
15\r
16**/\r
17#include "../Common/PcdCommon.h"\r
18#include "Service.h"\r
19\r
20static PCD_DATABASE *PrivatePcdDxeDatabase;\r
21static LIST_ENTRY mPcdDatabaseListHead = INITIALIZE_LIST_HEAD_VARIABLE(mPcdDatabaseListHead);\r
22\r
23LIST_ENTRY *\r
24GetPcdDatabaseListHead (\r
25 VOID\r
26 )\r
27{\r
28 return &mPcdDatabaseListHead;\r
29}\r
30\r
31PCD_DATABASE *\r
32GetPcdDxeDataBaseInstance (\r
33 VOID\r
34)\r
35{\r
36 return PrivatePcdDxeDatabase;\r
37}\r
38\r
39PCD_DATABASE *\r
40SetPcdDxeDataBaseInstance (\r
41 PCD_DATABASE *PcdDatabase\r
42)\r
43{\r
44 return PrivatePcdDxeDatabase = PcdDatabase;\r
45}\r
46\r
47\r
48VOID\r
49DxeGetPcdEntryWorker (\r
50 IN UINTN TokenNumber,\r
51 IN CONST GUID *Guid, OPTIONAL\r
52 IN PCD_DATA_TYPE Type,\r
53 OUT VOID *Data\r
54 )\r
55{\r
56 PCD_DATABASE *Database;\r
57 Database = GetPcdDxeDataBaseInstance ();\r
58\r
59 GetPcdEntryWorker ( &Database->Info,\r
60 TokenNumber,\r
61 Guid,\r
62 Type,\r
63 Data\r
64 );\r
65\r
66\r
67 return;\r
68}\r
69\r
70\r
71\r
72EFI_STATUS\r
73DxeSetPcdEntryWorker (\r
74 IN UINTN TokenNumber,\r
75 IN CONST GUID *Guid, OPTIONAL\r
76 IN PCD_DATA_TYPE Type,\r
77 IN CONST VOID *Data\r
78 )\r
79{\r
80 PCD_DATABASE *Database;\r
81 PCD_INDEX *PcdIndex;\r
82 EFI_STATUS Status;\r
83\r
84 Database = GetPcdDxeDataBaseInstance ();\r
85\r
86\r
87 ASSERT (Data != NULL);\r
88\r
89 PcdIndex = FindPcdIndex (TokenNumber, Guid, &Database->Info, NULL);\r
90\r
91 ASSERT (PcdIndex != NULL);\r
92\r
93 ASSERT (PcdIndex->StateByte.DataType == Type);\r
94\r
95 //\r
96 // Invoke the callback function.\r
97 //\r
98\r
99 Status = SetPcdData (PcdIndex, &Database->Info, Data);\r
100\r
101 return Status;\r
102\r
103\r
104}\r
105\r
106\r
107\r
108UINTN\r
109DxeGetPcdEntrySizeWorker (\r
110 IN UINTN TokenNumber,\r
111 IN CONST GUID *Guid OPTIONAL\r
112 )\r
113{\r
114 PCD_DATABASE *Database;\r
115 Database = GetPcdDxeDataBaseInstance ();\r
116\r
117 return GetPcdEntrySizeWorker (&Database->Info,\r
118 TokenNumber,\r
119 Guid\r
120 );\r
121}\r
122\r
123\r
124\r
125LIST_ENTRY *\r
126InsertToGuidSpaceListI (\r
127 IN LIST_ENTRY *GuidSpaceListHead,\r
128 IN CONST EFI_GUID *Guid\r
129 )\r
130{\r
131 PCD_GUID_SPACE *GuidSpaceEntry;\r
132\r
133 GuidSpaceEntry = AllocatePool (sizeof (PCD_GUID_SPACE));\r
134 ASSERT (GuidSpaceEntry != NULL);\r
135\r
136 GuidSpaceEntry->GuidSpace= Guid;\r
137 InitializeListHead (&GuidSpaceEntry->TokenSpaceHead);\r
138 \r
139 InsertTailList (GuidSpaceListHead, &GuidSpaceEntry->ListNode);\r
140\r
141 return &GuidSpaceEntry->TokenSpaceHead;\r
142}\r
143\r
144\r
145\r
146LIST_ENTRY *\r
147InsertToTokenSpaceListI (\r
148 IN LIST_ENTRY *TokenSpaceListHead,\r
149 IN UINTN TokenNumber\r
150 )\r
151{\r
152 PCD_TOKEN_SPACE *TokenSpaceEntry;\r
153\r
154 TokenSpaceEntry = AllocatePool (sizeof (PCD_TOKEN_SPACE));\r
155 ASSERT (TokenSpaceEntry != NULL);\r
156\r
157 TokenSpaceEntry->TokeNumber = TokenNumber;\r
158 InitializeListHead (&TokenSpaceEntry->CallbackListHead);\r
159 \r
160 InsertTailList (TokenSpaceListHead, &TokenSpaceEntry->ListNode);\r
161\r
162 return &TokenSpaceEntry->CallbackListHead;\r
163}\r
164\r
165\r
166\r
167VOID\r
168InsertToCallbackListI (\r
169 IN LIST_ENTRY *CallbackListHead,\r
170 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
171 )\r
172{\r
173 PCD_CALLBACK_ENTRY *CallbackEntry;\r
174 \r
175 CallbackEntry = AllocatePool (sizeof (PCD_CALLBACK_ENTRY));\r
176 ASSERT (CallbackEntry != NULL);\r
177 CallbackEntry->CallbackFunction = CallBackFunction;\r
178 InsertTailList (CallbackListHead, &CallbackEntry->ListNode);\r
179 \r
180 return;\r
181}\r
182\r
183\r
184\r
185\r
186VOID\r
187InsertToCallbackList (\r
188 IN UINTN TokenNumber,\r
189 IN CONST EFI_GUID *Guid,\r
190 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
191 )\r
192{\r
193 LIST_ENTRY *GuidListNode;\r
194 LIST_ENTRY *GuidListHead;\r
195 LIST_ENTRY *TokenListNode;\r
196 LIST_ENTRY *TokenListHead;\r
197 LIST_ENTRY *CallbackListHead;\r
198 PCD_GUID_SPACE *GuidSpaceEntry;\r
199 PCD_TOKEN_SPACE *TokenSpaceEntry;\r
200\r
201 \r
202 GuidListHead = GetPcdDatabaseListHead ();\r
203\r
204 GuidListNode = GetFirstNode (GuidListHead);\r
205 while (!IsNull (GuidListNode, GuidListHead)) {\r
206 GuidSpaceEntry = PCD_GUID_SPACE_FROM_LISTNODE(GuidListNode);\r
207\r
208 if (CompareGuid (GuidSpaceEntry->GuidSpace, Guid)) {\r
209 TokenListHead = &GuidSpaceEntry->TokenSpaceHead;\r
210 TokenListNode = GetFirstNode (TokenListHead);\r
211 while (!IsNull (TokenListNode, TokenListHead)) {\r
212 TokenSpaceEntry = PCD_TOKEN_SPACE_FROM_LISTNODE(TokenListNode);\r
213 if (TokenSpaceEntry->TokeNumber == TokenNumber) {\r
214 InsertToCallbackListI (&TokenSpaceEntry->CallbackListHead , CallBackFunction);\r
215 }\r
216 }\r
217\r
218 //\r
219 // No TokenNumber match input found in this GuidSpace\r
220 //\r
221 CallbackListHead = InsertToTokenSpaceListI (TokenListHead, TokenNumber);\r
222 InsertToCallbackListI (CallbackListHead , CallBackFunction);\r
223 }\r
224 \r
225 GuidListNode = GetNextNode (GuidListHead, GuidListNode);\r
226 }\r
227\r
228 //\r
229 // No GuidSpace match the input Guid, so build the GuidSpace, TokenNumberSpace and Callback\r
230 //\r
231 TokenListHead = InsertToGuidSpaceListI (GuidListHead, Guid);\r
232 CallbackListHead = InsertToTokenSpaceListI (TokenListHead, TokenNumber);\r
233 InsertToCallbackListI (CallbackListHead , CallBackFunction);\r
234\r
235 return;\r
236 \r
237}\r
238\r
239EFI_STATUS\r
240RemoveFromCallbackListI (\r
241 IN LIST_ENTRY *CallbackListHead,\r
242 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
243 )\r
244{\r
245 LIST_ENTRY *ListNode;\r
246 PCD_CALLBACK_ENTRY *CallbackEntry;\r
247\r
248 ListNode = GetFirstNode (CallbackListHead);\r
249\r
250 while (!IsNull(CallbackListHead, ListNode)) {\r
251 CallbackEntry = PCD_CALLBACK_ENTRY_FROM_LISTNODE(ListNode);\r
252\r
253 if (CallbackEntry->CallbackFunction == CallBackFunction) {\r
254 RemoveEntryList (ListNode);\r
255 FreePool (CallbackEntry);\r
256 return EFI_SUCCESS;\r
257 }\r
258 ListNode = GetNextNode (CallbackListHead, ListNode);\r
259 }\r
260\r
261 return EFI_NOT_FOUND;\r
262}\r
263\r
264\r
265\r
266EFI_STATUS\r
267RemoveFromCallbackList (\r
268 IN UINTN TokenNumber,\r
269 IN CONST GUID *Guid,\r
270 IN PCD_PROTOCOL_CALLBACK CallBackFunction\r
271 )\r
272{\r
273 LIST_ENTRY *GuidListNode;\r
274 LIST_ENTRY *GuidListHead;\r
275 LIST_ENTRY *TokenListNode;\r
276 LIST_ENTRY *TokenListHead;\r
277 PCD_GUID_SPACE *GuidSpaceEntry;\r
278 PCD_TOKEN_SPACE *TokenSpaceEntry;\r
279\r
280 \r
281 GuidListHead = GetPcdDatabaseListHead ();\r
282\r
283 GuidListNode = GetFirstNode (GuidListHead);\r
284 while (!IsNull (GuidListNode, GuidListHead)) {\r
285 \r
286 GuidSpaceEntry = PCD_GUID_SPACE_FROM_LISTNODE(GuidListNode);\r
287 if (CompareGuid (GuidSpaceEntry->GuidSpace, Guid)) {\r
288 \r
289 TokenListHead = &GuidSpaceEntry->TokenSpaceHead;\r
290 TokenListNode = GetFirstNode (TokenListHead);\r
291 while (!IsNull (TokenListNode, TokenListHead)) {\r
292 \r
293 TokenSpaceEntry = PCD_TOKEN_SPACE_FROM_LISTNODE(TokenListNode);\r
294 if (TokenSpaceEntry->TokeNumber == TokenNumber) {\r
295 return RemoveFromCallbackListI (&TokenSpaceEntry->CallbackListHead , CallBackFunction);\r
296 }\r
297 }\r
298\r
299 //\r
300 // No TokenNumber match input found in this GuidSpace\r
301 //\r
302 return EFI_NOT_FOUND;\r
303 }\r
304 \r
305 GuidListNode = GetNextNode (GuidListHead, GuidListNode);\r
306 }\r
307\r
308\r
309 return EFI_NOT_FOUND;\r
310 \r
311}\r
312\r
313\r
314\r
315EFI_STATUS\r
316DxeRegisterCallBackWorker (\r
317 IN UINTN TokenNumber,\r
318 IN CONST GUID *Guid, OPTIONAL\r
319 IN PCD_PROTOCOL_CALLBACK CallBackFunction,\r
320 IN BOOLEAN Register\r
321)\r
322{\r
323 PCD_DATABASE *Database;\r
324 PCD_INDEX *PcdIndex;\r
325 \r
326 Database = GetPcdDxeDataBaseInstance ();\r
327\r
328 PcdIndex = FindPcdIndex (TokenNumber, Guid, &Database->Info, NULL);\r
329\r
330 if (PcdIndex == NULL) {\r
331 return EFI_NOT_FOUND;\r
332 }\r
333\r
334 if (Register) {\r
335 InsertToCallbackList (TokenNumber, Guid, CallBackFunction);\r
336 return EFI_SUCCESS;\r
337 } else {\r
338 return RemoveFromCallbackList (TokenNumber, Guid, CallBackFunction); \r
339 }\r
340\r
341 }\r
342\r
343\r
344\r
345EFI_STATUS\r
346DxeSetSku (\r
347 UINTN Id\r
348)\r
349{\r
350 PCD_DATABASE * Database;\r
351\r
352 Database = GetPcdDxeDataBaseInstance ();\r
353\r
354 return Database->Info.SkuId = Id;\r
355\r
356}\r
357\r
358\r
359\r
360EFI_STATUS\r
361DxeGetNextTokenWorker (\r
362 IN OUT UINTN *TokenNumber,\r
363 IN CONST GUID *Guid OPTIONAL\r
364 )\r
365{\r
366 PCD_DATABASE * Database;\r
367\r
368 Database = GetPcdDxeDataBaseInstance ();\r
369\r
370 return GetNextTokenWorker (&Database->Info,\r
371 TokenNumber,\r
372 Guid\r
373 );\r
374}\r
375\r
376\r
377\r
378VOID\r
379InitPcdDxeDataBase (\r
380 VOID\r
381)\r
382{\r
383 PCD_DATABASE *PeiDatabase;\r
384 PCD_DATABASE *DxeDatabase;\r
385 EFI_HOB_GUID_TYPE *GuidHob;\r
386\r
387 GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);\r
388 ASSERT (GuidHob != NULL);\r
389\r
390 PeiDatabase = (PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob);\r
391\r
392 DxeDatabase = AllocateCopyPool (PeiDatabase->Info.DatabaseLen, PeiDatabase);\r
393\r
394 ASSERT (DxeDatabase != NULL);\r
395\r
396 SetPcdDxeDataBaseInstance (DxeDatabase);\r
397\r
398 return;\r
399}\r
400\r
401\r
402\r
403EFI_STATUS\r
404GetHiiVariable (\r
405 IN EFI_GUID *VariableGuid,\r
406 IN UINT16 *VariableName,\r
407 OUT VOID ** VariableData,\r
408 OUT UINTN *VariableSize\r
409 )\r
410{\r
411 UINTN Size;\r
412 EFI_STATUS Status;\r
413 VOID *Buffer;\r
414\r
415 Status = EfiGetVariable (\r
416 (UINT16 *)VariableName,\r
417 VariableGuid,\r
418 NULL,\r
419 &Size,\r
420 NULL\r
421 );\r
422 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
423\r
424 Buffer = AllocatePool (Size);\r
425\r
426 ASSERT (Buffer != NULL);\r
427\r
428 Status = EfiGetVariable (\r
429 VariableName,\r
430 VariableGuid,\r
431 NULL,\r
432 &Size,\r
433 Buffer\r
434 );\r
435\r
436 return Status;\r
437\r
438}\r
439\r
440\r
441\r
442EFI_STATUS\r
443SetHiiVariable (\r
444 IN EFI_GUID *VariableGuid,\r
445 IN UINT16 *VariableName,\r
446 IN CONST VOID *Data,\r
447 IN UINTN DataSize,\r
448 IN UINTN Offset\r
449 )\r
450{\r
451 UINTN Size;\r
452 VOID *Buffer;\r
453 EFI_STATUS Status;\r
454\r
455 Size = 0;\r
456\r
457 Status = EfiGetVariable (\r
458 (UINT16 *)VariableName,\r
459 VariableGuid,\r
460 NULL,\r
461 &Size,\r
462 NULL\r
463 );\r
464\r
465 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
466\r
467 Buffer = AllocatePool (Size);\r
468\r
469 ASSERT (Buffer != NULL);\r
470\r
471 Status = EfiGetVariable (\r
472 VariableName,\r
473 VariableGuid,\r
474 NULL,\r
475 &Size,\r
476 Buffer\r
477 );\r
478\r
479\r
480 CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
481\r
482 return EfiSetVariable (\r
483 VariableName,\r
484 VariableGuid,\r
485 0,\r
486 Size,\r
487 Buffer\r
488 );\r
489\r
490}\r
491\r