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