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