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