Add more check for index whether exceed maximum value of fv count.
[mirror_edk2.git] / EdkModulePkg / Library / EdkFvbServiceLib / x64 / Fvb.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 Fvb.c \r
15\r
16Abstract:\r
17\r
18 Firmware Volume Block Protocol Runtime Abstraction\r
19\r
20 mFvbEntry is an array of Handle Fvb pairs. The Fvb Lib Instance matches the \r
21 index in the mFvbEntry array. This should be the same sequence as the FVB's\r
22 were described in the HOB. We have to remember the handle so we can tell if \r
23 the protocol has been reinstalled and it needs updateing.\r
24\r
25 If you are using any of these lib functions.you must first call FvbInitialize ().\r
26\r
27Key:\r
28 FVB - Firmware Volume Block\r
29\r
30--*/\r
31\r
32#include "Fvb.h"\r
33\r
34//\r
35// Lib will ASSERT if more FVB devices than this are added to the system.\r
36//\r
37STATIC FVB_ENTRY *mFvbEntry;\r
0cc82df1 38// STATIC EFI_EVENT mFvbVirtualNotifyEvent;\r
878ddf1f 39STATIC EFI_EVENT mFvbRegistration;\r
0cc82df1 40// STATIC EFI_EVENT mEfiFvbVirtualNotifyEvent;\r
878ddf1f 41STATIC BOOLEAN mEfiFvbInitialized = FALSE;\r
42STATIC UINTN mFvbCount;\r
43\r
44STATIC\r
45VOID\r
46EFIAPI\r
47FvbNotificationEvent (\r
48 IN EFI_EVENT Event,\r
49 IN VOID *Context\r
50 )\r
51/*++\r
52\r
53Routine Description:\r
54 Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is\r
55 reinstalled.\r
56\r
57Arguments:\r
58\r
59 Event - The Event that is being processed\r
60 \r
61 Context - Event Context\r
62\r
63Returns: \r
64 None\r
65\r
66--*/\r
67{\r
68 EFI_STATUS Status;\r
69 UINTN BufferSize;\r
70 EFI_HANDLE Handle;\r
71 UINTN Index;\r
72 UINTN UpdateIndex;\r
73\r
74 while (TRUE) {\r
75 BufferSize = sizeof (Handle);\r
76 Status = gBS->LocateHandle (\r
77 ByRegisterNotify,\r
78 &gEfiFirmwareVolumeBlockProtocolGuid,\r
79 mFvbRegistration,\r
80 &BufferSize,\r
81 &Handle\r
82 );\r
83 if (EFI_ERROR (Status)) {\r
84 //\r
85 // Exit Path of While Loop....\r
86 //\r
87 break;\r
88 }\r
89\r
90 UpdateIndex = MAX_FVB_COUNT;\r
91 for (Index = 0; Index < mFvbCount; Index++) {\r
92 if (mFvbEntry[Index].Handle == Handle) {\r
93 //\r
94 // If the handle is already in the table just update the protocol\r
95 //\r
96 UpdateIndex = Index;\r
97 break;\r
98 }\r
99 }\r
100\r
101 if (UpdateIndex == MAX_FVB_COUNT) {\r
102 //\r
103 // Use the next free slot for a new entry\r
104 //\r
a7207480 105 UpdateIndex = mFvbCount++;\r
106 ASSERT (UpdateIndex < MAX_FVB_COUNT); \r
878ddf1f 107 mFvbEntry[UpdateIndex].Handle = Handle;\r
108 }\r
109 //\r
110 // The array does not have enough entries\r
111 //\r
112 ASSERT (UpdateIndex < MAX_FVB_COUNT);\r
113\r
114 //\r
115 // Get the interface pointer and if it's ours, skip it\r
116 //\r
0cc82df1 117 Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&mFvbEntry[UpdateIndex].Fvb);\r
878ddf1f 118 ASSERT_EFI_ERROR (Status);\r
119\r
0cc82df1 120 Status = gBS->HandleProtocol (Handle, &gEfiFvbExtensionProtocolGuid, (VOID **)&mFvbEntry[UpdateIndex].FvbExtension);\r
878ddf1f 121 if (Status != EFI_SUCCESS) {\r
122 mFvbEntry[UpdateIndex].FvbExtension = NULL;\r
123 }\r
124 }\r
125}\r
126\r
127VOID\r
128EFIAPI\r
129FvbVirtualAddressChangeNotifyEvent (\r
130 IN EFI_EVENT Event,\r
131 IN VOID *Context\r
132 )\r
133/*++\r
134\r
135Routine Description:\r
136\r
137 Convert all pointers in mFvbEntry after ExitBootServices.\r
138\r
139Arguments:\r
140\r
141 Event - The Event that is being processed\r
142 \r
143 Context - Event Context\r
144\r
145Returns:\r
146\r
147 None\r
148\r
149--*/\r
150{\r
151 UINTN Index;\r
152 if (mFvbEntry != NULL) {\r
153 for (Index = 0; Index < MAX_FVB_COUNT; Index++) {\r
154 if (NULL != mFvbEntry[Index].Fvb) {\r
155 EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetBlockSize);\r
156 EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetPhysicalAddress);\r
157 EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetVolumeAttributes);\r
158 EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->SetVolumeAttributes);\r
159 EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Read);\r
160 EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Write);\r
161 EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->EraseBlocks);\r
162 EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb);\r
163 }\r
164\r
165 if (NULL != mFvbEntry[Index].FvbExtension) {\r
166 EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension->EraseFvbCustomBlock);\r
167 EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension);\r
168 }\r
169 }\r
170\r
171 EfiConvertPointer (0x0, (VOID **) &mFvbEntry);\r
172 }\r
173}\r
174\r
175EFI_STATUS\r
176EFIAPI\r
177FvbLibInitialize (\r
178 IN EFI_HANDLE ImageHandle,\r
179 IN EFI_SYSTEM_TABLE *SystemTable\r
180 )\r
181/*++\r
182\r
183Routine Description:\r
184 Initialize globals and register Fvb Protocol notification function.\r
185\r
186Arguments:\r
187 None \r
188\r
189Returns: \r
190 EFI_SUCCESS\r
191\r
192--*/\r
193{\r
194 UINTN Status;\r
195 mFvbCount = 0;\r
196\r
197 Status = gBS->AllocatePool (\r
198 EfiRuntimeServicesData,\r
199 (UINTN) sizeof (FVB_ENTRY) * MAX_FVB_COUNT,\r
200 (VOID *) &mFvbEntry\r
201 );\r
202\r
203 if (EFI_ERROR (Status)) {\r
204 return Status;\r
205 }\r
206\r
207 ZeroMem (mFvbEntry, sizeof (FVB_ENTRY) * MAX_FVB_COUNT);\r
208\r
209 EfiCreateProtocolNotifyEvent (\r
210 &gEfiFirmwareVolumeBlockProtocolGuid,\r
211 EFI_TPL_CALLBACK,\r
212 FvbNotificationEvent,\r
213 NULL,\r
214 &mFvbRegistration\r
215 );\r
216\r
217 //\r
218 // Register SetVirtualAddressMap () notify function\r
219 //\r
220 // Status = gBS->CreateEvent (\r
221 // EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,\r
222 // EFI_TPL_NOTIFY,\r
223 // EfiRuntimeLibFvbVirtualNotifyEvent,\r
224 // NULL,\r
225 // &mEfiFvbVirtualNotifyEvent\r
226 // );\r
227 // ASSERT_EFI_ERROR (Status);\r
228 //\r
229\r
230 //\r
231 // Register SetVirtualAddressMap () notify function\r
232 //\r
233\r
234 ASSERT_EFI_ERROR (Status);\r
235\r
236 mEfiFvbInitialized = TRUE;\r
237\r
238 return EFI_SUCCESS;\r
239}\r
240//\r
241// The following functions wrap Fvb protocol in the Runtime Lib functions.\r
242// The Instance translates into Fvb instance. The Fvb order defined by HOBs and\r
243// thus the sequence of FVB protocol addition define Instance.\r
244//\r
245// EfiFvbInitialize () must be called before any of the following functions\r
246// must be called.\r
247//\r
248\r
249EFI_STATUS\r
250EfiFvbReadBlock (\r
251 IN UINTN Instance,\r
252 IN EFI_LBA Lba,\r
253 IN UINTN Offset,\r
254 IN OUT UINTN *NumBytes,\r
255 IN UINT8 *Buffer\r
256 )\r
257/*++\r
258\r
259Routine Description:\r
260 Reads specified number of bytes into a buffer from the specified block\r
261\r
262Arguments:\r
263 Instance - The FV instance to be read from\r
264 Lba - The logical block address to be read from\r
265 Offset - Offset into the block at which to begin reading\r
266 NumBytes - Pointer that on input contains the total size of\r
267 the buffer. On output, it contains the total number\r
268 of bytes read\r
269 Buffer - Pointer to a caller allocated buffer that will be\r
270 used to hold the data read\r
271\r
272Returns: \r
273\r
274 Status code\r
275 \r
276 EFI_INVALID_PARAMETER - invalid parameter\r
277\r
278--*/\r
279{\r
280 if (Instance >= mFvbCount) {\r
281 return EFI_INVALID_PARAMETER;\r
282 }\r
283\r
284 return mFvbEntry[Instance].Fvb->Read (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer);\r
285}\r
286\r
287EFI_STATUS\r
288EfiFvbWriteBlock (\r
289 IN UINTN Instance,\r
290 IN EFI_LBA Lba,\r
291 IN UINTN Offset,\r
292 IN OUT UINTN *NumBytes,\r
293 IN UINT8 *Buffer\r
294 )\r
295/*++\r
296\r
297Routine Description:\r
298 Writes specified number of bytes from the input buffer to the block\r
299\r
300Arguments:\r
301 Instance - The FV instance to be written to\r
302 Lba - The starting logical block index to write to\r
303 Offset - Offset into the block at which to begin writing\r
304 NumBytes - Pointer that on input contains the total size of\r
305 the buffer. On output, it contains the total number\r
306 of bytes actually written\r
307 Buffer - Pointer to a caller allocated buffer that contains\r
308 the source for the write\r
309\r
310Returns: \r
311\r
312 Status code\r
313 \r
314 EFI_INVALID_PARAMETER - invalid parameter\r
315\r
316--*/\r
317{\r
318 if (Instance >= mFvbCount) {\r
319 return EFI_INVALID_PARAMETER;\r
320 }\r
321\r
322 return mFvbEntry[Instance].Fvb->Write (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer);\r
323}\r
324\r
325EFI_STATUS\r
326EfiFvbEraseBlock (\r
327 IN UINTN Instance,\r
328 IN EFI_LBA Lba\r
329 )\r
330/*++\r
331\r
332Routine Description:\r
333 Erases and initializes a firmware volume block\r
334\r
335Arguments:\r
336 Instance - The FV instance to be erased\r
337 Lba - The logical block index to be erased\r
338 \r
339Returns: \r
340\r
341 Status code\r
342 \r
343 EFI_INVALID_PARAMETER - invalid parameter\r
344\r
345--*/\r
346{\r
347 if (Instance >= mFvbCount) {\r
348 return EFI_INVALID_PARAMETER;\r
349 }\r
350\r
351 return mFvbEntry[Instance].Fvb->EraseBlocks (mFvbEntry[Instance].Fvb, Lba, -1);\r
352}\r
353\r
354EFI_STATUS\r
355EfiFvbGetVolumeAttributes (\r
356 IN UINTN Instance,\r
357 OUT EFI_FVB_ATTRIBUTES *Attributes\r
358 )\r
359/*++\r
360\r
361Routine Description:\r
362 Retrieves attributes, insures positive polarity of attribute bits, returns\r
363 resulting attributes in output parameter\r
364\r
365Arguments:\r
366 Instance - The FV instance whose attributes is going to be \r
367 returned\r
368 Attributes - Output buffer which contains attributes\r
369\r
370Returns: \r
371 Status code\r
372 \r
373 EFI_INVALID_PARAMETER - invalid parameter\r
374\r
375--*/\r
376{\r
377 if (Instance >= mFvbCount) {\r
378 return EFI_INVALID_PARAMETER;\r
379 }\r
380\r
381 return mFvbEntry[Instance].Fvb->GetVolumeAttributes (mFvbEntry[Instance].Fvb, Attributes);\r
382}\r
383\r
384EFI_STATUS\r
385EfiFvbSetVolumeAttributes (\r
386 IN UINTN Instance,\r
387 IN EFI_FVB_ATTRIBUTES Attributes\r
388 )\r
389/*++\r
390\r
391Routine Description:\r
392 Modifies the current settings of the firmware volume according to the \r
393 input parameter, and returns the new setting of the volume\r
394\r
395Arguments:\r
396 Instance - The FV instance whose attributes is going to be \r
397 modified\r
398 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES \r
399 containing the desired firmware volume settings.\r
400 On successful return, it contains the new settings\r
401 of the firmware volume\r
402\r
403Returns: \r
404 Status code\r
405 \r
406 EFI_INVALID_PARAMETER - invalid parameter\r
407\r
408--*/\r
409{\r
410 if (Instance >= mFvbCount) {\r
411 return EFI_INVALID_PARAMETER;\r
412 }\r
413\r
414 return mFvbEntry[Instance].Fvb->SetVolumeAttributes (mFvbEntry[Instance].Fvb, &Attributes);\r
415}\r
416\r
417EFI_STATUS\r
418EfiFvbGetPhysicalAddress (\r
419 IN UINTN Instance,\r
420 OUT EFI_PHYSICAL_ADDRESS *BaseAddress\r
421 )\r
422/*++\r
423\r
424Routine Description:\r
425 Retrieves the physical address of a memory mapped FV\r
426\r
427Arguments:\r
428 Instance - The FV instance whose base address is going to be\r
429 returned\r
430 BaseAddress - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS \r
431 that on successful return, contains the base address\r
432 of the firmware volume. \r
433\r
434Returns: \r
435\r
436 Status code\r
437 \r
438 EFI_INVALID_PARAMETER - invalid parameter\r
439\r
440--*/\r
441{\r
442 if (Instance >= mFvbCount) {\r
443 return EFI_INVALID_PARAMETER;\r
444 }\r
445\r
446 return mFvbEntry[Instance].Fvb->GetPhysicalAddress (mFvbEntry[Instance].Fvb, BaseAddress);\r
447}\r
448\r
449EFI_STATUS\r
450EfiFvbGetBlockSize (\r
451 IN UINTN Instance,\r
452 IN EFI_LBA Lba,\r
453 OUT UINTN *BlockSize,\r
454 OUT UINTN *NumOfBlocks\r
455 )\r
456/*++\r
457\r
458Routine Description:\r
459 Retrieve the size of a logical block\r
460\r
461Arguments:\r
462 Instance - The FV instance whose block size is going to be\r
463 returned\r
464 Lba - Indicates which block to return the size for.\r
465 BlockSize - A pointer to a caller allocated UINTN in which\r
466 the size of the block is returned\r
467 NumOfBlocks - a pointer to a caller allocated UINTN in which the\r
468 number of consecutive blocks starting with Lba is\r
469 returned. All blocks in this range have a size of\r
470 BlockSize\r
471\r
472Returns: \r
473 EFI_SUCCESS - The firmware volume was read successfully and \r
474 contents are in Buffer\r
475 \r
476 EFI_INVALID_PARAMETER - invalid parameter\r
477\r
478--*/\r
479{\r
480 if (Instance >= mFvbCount) {\r
481 return EFI_INVALID_PARAMETER;\r
482 }\r
483\r
484 return mFvbEntry[Instance].Fvb->GetBlockSize (mFvbEntry[Instance].Fvb, Lba, BlockSize, NumOfBlocks);\r
485}\r
486\r
487EFI_STATUS\r
488EfiFvbEraseCustomBlockRange (\r
489 IN UINTN Instance,\r
490 IN EFI_LBA StartLba,\r
491 IN UINTN OffsetStartLba,\r
492 IN EFI_LBA LastLba,\r
493 IN UINTN OffsetLastLba\r
494 )\r
495/*++\r
496\r
497Routine Description:\r
498 Erases and initializes a specified range of a firmware volume\r
499\r
500Arguments:\r
501 Instance - The FV instance to be erased\r
502 StartLba - The starting logical block index to be erased\r
503 OffsetStartLba - Offset into the starting block at which to \r
504 begin erasing\r
505 LastLba - The last logical block index to be erased\r
506 OffsetLastLba - Offset into the last block at which to end erasing\r
507\r
508Returns: \r
509\r
510 Status code\r
511 \r
512 EFI_INVALID_PARAMETER - invalid parameter\r
513 \r
514 EFI_UNSUPPORTED - not support\r
515 \r
516--*/\r
517{\r
518 if (Instance >= mFvbCount) {\r
519 return EFI_INVALID_PARAMETER;\r
520 }\r
521\r
522 if (!(mFvbEntry[Instance].FvbExtension)) {\r
523 return EFI_UNSUPPORTED;\r
524 }\r
525\r
526 if (!(mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock)) {\r
527 return EFI_UNSUPPORTED;\r
528 }\r
529\r
530 return mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock (\r
531 mFvbEntry[Instance].FvbExtension,\r
532 StartLba,\r
533 OffsetStartLba,\r
534 LastLba,\r
535 OffsetLastLba\r
536 );\r
537}\r