]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
MmcDxe Diagnostics: return EFI_UNSUPPORTED for Language other than english
[mirror_edk2.git] / EmbeddedPkg / Universal / MmcDxe / MmcBlockIo.c
1 /** @file
2 *
3 * Copyright (c) 2011-2013, ARM Limited. All rights reserved.
4 *
5 * 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
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/TimerLib.h>
17
18 #include "Mmc.h"
19
20 #define MAX_RETRY_COUNT 1000
21 #define CMD_RETRY_COUNT 20
22
23 EFI_STATUS
24 MmcNotifyState (
25 IN MMC_HOST_INSTANCE *MmcHostInstance,
26 IN MMC_STATE State
27 )
28 {
29 MmcHostInstance->State = State;
30 return MmcHostInstance->MmcHost->NotifyState (MmcHostInstance->MmcHost, State);
31 }
32
33 EFI_STATUS
34 EFIAPI
35 MmcGetCardStatus (
36 IN MMC_HOST_INSTANCE *MmcHostInstance
37 )
38 {
39 EFI_STATUS Status;
40 UINT32 Response[4];
41 UINTN CmdArg;
42 EFI_MMC_HOST_PROTOCOL *MmcHost;
43
44 Status = EFI_SUCCESS;
45 MmcHost = MmcHostInstance->MmcHost;
46 CmdArg = 0;
47
48 if (MmcHost == NULL) {
49 return EFI_INVALID_PARAMETER;
50 }
51 if (MmcHostInstance->State != MmcHwInitializationState) {
52 //Get the Status of the card.
53 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
54 Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
55 if (EFI_ERROR (Status)) {
56 DEBUG ((EFI_D_ERROR, "MmcGetCardStatus(MMC_CMD13): Error and Status = %r\n", Status));
57 return Status;
58 }
59
60 //Read Response
61 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
62 PrintResponseR1 (Response[0]);
63 }
64
65 return Status;
66 }
67
68 EFI_STATUS
69 EFIAPI
70 MmcIdentificationMode (
71 IN MMC_HOST_INSTANCE *MmcHostInstance
72 )
73 {
74 EFI_STATUS Status;
75 UINT32 Response[4];
76 UINTN Timeout;
77 UINTN CmdArg;
78 BOOLEAN IsHCS;
79 EFI_MMC_HOST_PROTOCOL *MmcHost;
80
81 MmcHost = MmcHostInstance->MmcHost;
82 CmdArg = 0;
83 IsHCS = FALSE;
84
85 if (MmcHost == NULL) {
86 return EFI_INVALID_PARAMETER;
87 }
88
89 // We can get into this function if we restart the identification mode
90 if (MmcHostInstance->State == MmcHwInitializationState) {
91 // Initialize the MMC Host HW
92 Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);
93 if (EFI_ERROR (Status)) {
94 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState\n"));
95 return Status;
96 }
97 }
98
99 Status = MmcHost->SendCommand (MmcHost, MMC_CMD0, 0);
100 if (EFI_ERROR (Status)) {
101 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD0): Error\n"));
102 return Status;
103 }
104
105 Status = MmcNotifyState (MmcHostInstance, MmcIdleState);
106 if (EFI_ERROR (Status)) {
107 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdleState\n"));
108 return Status;
109 }
110
111 // Are we using SDIO ?
112 Status = MmcHost->SendCommand (MmcHost, MMC_CMD5, 0);
113 if (Status == EFI_SUCCESS) {
114 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported.\n"));
115 return EFI_UNSUPPORTED;
116 }
117
118 // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)
119 CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);
120 Status = MmcHost->SendCommand (MmcHost, MMC_CMD8, CmdArg);
121 if (Status == EFI_SUCCESS) {
122 DEBUG ((EFI_D_ERROR, "Card is SD2.0 => Supports high capacity\n"));
123 IsHCS = TRUE;
124 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R7, Response);
125 PrintResponseR1 (Response[0]);
126 //check if it is valid response
127 if (Response[0] != CmdArg) {
128 DEBUG ((EFI_D_ERROR, "The Card is not usable\n"));
129 return EFI_UNSUPPORTED;
130 }
131 } else {
132 DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));
133 }
134
135 // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.PowerUp == 1)
136 Timeout = MAX_RETRY_COUNT;
137 while (Timeout > 0) {
138 // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command
139 Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, 0);
140 if (Status == EFI_SUCCESS) {
141 DEBUG ((EFI_D_INFO, "Card should be SD\n"));
142 if (IsHCS) {
143 MmcHostInstance->CardInfo.CardType = SD_CARD_2;
144 } else {
145 MmcHostInstance->CardInfo.CardType = SD_CARD;
146 }
147
148 // Note: The first time CmdArg will be zero
149 CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];
150 if (IsHCS) {
151 CmdArg |= BIT30;
152 }
153 Status = MmcHost->SendCommand (MmcHost, MMC_ACMD41, CmdArg);
154 if (!EFI_ERROR (Status)) {
155 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);
156 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
157 }
158 } else {
159 DEBUG ((EFI_D_INFO, "Card should be MMC\n"));
160 MmcHostInstance->CardInfo.CardType = MMC_CARD;
161
162 Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, 0x800000);
163 if (!EFI_ERROR (Status)) {
164 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);
165 ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
166 }
167 }
168
169 if (!EFI_ERROR (Status)) {
170 if (!MmcHostInstance->CardInfo.OCRData.PowerUp) {
171 MicroSecondDelay (1);
172 Timeout--;
173 } else {
174 if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {
175 MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;
176 DEBUG ((EFI_D_ERROR, "High capacity card.\n"));
177 }
178 break; // The MMC/SD card is ready. Continue the Identification Mode
179 }
180 } else {
181 MicroSecondDelay (1);
182 Timeout--;
183 }
184 }
185
186 if (Timeout == 0) {
187 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));
188 return EFI_NO_MEDIA;
189 } else {
190 PrintOCR (Response[0]);
191 }
192
193 Status = MmcNotifyState (MmcHostInstance, MmcReadyState);
194 if (EFI_ERROR (Status)) {
195 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));
196 return Status;
197 }
198
199 Status = MmcHost->SendCommand (MmcHost, MMC_CMD2, 0);
200 if (EFI_ERROR (Status)) {
201 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));
202 return Status;
203 }
204 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CID, Response);
205 PrintCID (Response);
206
207 Status = MmcNotifyState (MmcHostInstance, MmcIdentificationState);
208 if (EFI_ERROR (Status)) {
209 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));
210 return Status;
211 }
212
213 //
214 // Note, SD specifications say that "if the command execution causes a state change, it
215 // will be visible to the host in the response to the next command"
216 // The status returned for this CMD3 will be 2 - identification
217 //
218 CmdArg = 1;
219 Status = MmcHost->SendCommand (MmcHost, MMC_CMD3, CmdArg);
220 if (EFI_ERROR (Status)) {
221 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));
222 return Status;
223 }
224
225 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_RCA, Response);
226 PrintRCA (Response[0]);
227
228 // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card
229 if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {
230 MmcHostInstance->CardInfo.RCA = Response[0] >> 16;
231 } else {
232 MmcHostInstance->CardInfo.RCA = CmdArg;
233 }
234
235 Status = MmcNotifyState (MmcHostInstance, MmcStandByState);
236 if (EFI_ERROR (Status)) {
237 DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));
238 return Status;
239 }
240
241 return EFI_SUCCESS;
242 }
243
244 EFI_STATUS InitializeMmcDevice (
245 IN MMC_HOST_INSTANCE *MmcHostInstance
246 )
247 {
248 UINT32 Response[4];
249 EFI_STATUS Status;
250 UINTN CardSize, NumBlocks, BlockSize, CmdArg;
251 EFI_MMC_HOST_PROTOCOL *MmcHost;
252 UINTN BlockCount;
253
254 BlockCount = 1;
255 MmcHost = MmcHostInstance->MmcHost;
256
257 MmcIdentificationMode (MmcHostInstance);
258
259 //Send a command to get Card specific data
260 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
261 Status = MmcHost->SendCommand (MmcHost, MMC_CMD9, CmdArg);
262 if (EFI_ERROR (Status)) {
263 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD9): Error, Status=%r\n", Status));
264 return Status;
265 }
266 //Read Response
267 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CSD, Response);
268 PrintCSD (Response);
269
270 if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
271 CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);
272 NumBlocks = ((CardSize + 1) * 1024);
273 BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);
274 } else {
275 CardSize = MMC_CSD_GET_DEVICESIZE (Response);
276 NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT (Response) + 2));
277 BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);
278 }
279
280 //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
281 if (BlockSize > 512) {
282 NumBlocks = MultU64x32 (NumBlocks, BlockSize/512);
283 BlockSize = 512;
284 }
285
286 MmcHostInstance->BlockIo.Media->LastBlock = (NumBlocks - 1);
287 MmcHostInstance->BlockIo.Media->BlockSize = BlockSize;
288 MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly (MmcHost);
289 MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;
290 MmcHostInstance->BlockIo.Media->MediaId++;
291
292 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
293 Status = MmcHost->SendCommand (MmcHost, MMC_CMD7, CmdArg);
294 if (EFI_ERROR (Status)) {
295 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD7): Error and Status = %r\n", Status));
296 return Status;
297 }
298
299 Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
300 if (EFI_ERROR (Status)) {
301 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(): Error MmcTransferState\n"));
302 return Status;
303 }
304
305 // Set Block Length
306 Status = MmcHost->SendCommand (MmcHost, MMC_CMD16, MmcHostInstance->BlockIo.Media->BlockSize);
307 if (EFI_ERROR (Status)) {
308 DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD16): Error MmcHostInstance->BlockIo.Media->BlockSize: %d and Error = %r\n",
309 MmcHostInstance->BlockIo.Media->BlockSize, Status));
310 return Status;
311 }
312
313 // Block Count (not used). Could return an error for SD card
314 if (MmcHostInstance->CardInfo.CardType == MMC_CARD) {
315 MmcHost->SendCommand (MmcHost, MMC_CMD23, BlockCount);
316 }
317
318 return EFI_SUCCESS;
319 }
320
321 EFI_STATUS
322 EFIAPI
323 MmcReset (
324 IN EFI_BLOCK_IO_PROTOCOL *This,
325 IN BOOLEAN ExtendedVerification
326 )
327 {
328 MMC_HOST_INSTANCE *MmcHostInstance;
329
330 MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
331
332 if (MmcHostInstance->MmcHost == NULL) {
333 // Nothing to do
334 return EFI_SUCCESS;
335 }
336
337 // If a card is not present then clear all media settings
338 if (!MmcHostInstance->MmcHost->IsCardPresent (MmcHostInstance->MmcHost)) {
339 MmcHostInstance->BlockIo.Media->MediaPresent = FALSE;
340 MmcHostInstance->BlockIo.Media->LastBlock = 0;
341 MmcHostInstance->BlockIo.Media->BlockSize = 512; // Should be zero but there is a bug in DiskIo
342 MmcHostInstance->BlockIo.Media->ReadOnly = FALSE;
343
344 // Indicate that the driver requires initialization
345 MmcHostInstance->State = MmcHwInitializationState;
346
347 return EFI_SUCCESS;
348 }
349
350 // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn
351 // on power and restart Identification mode
352 return EFI_SUCCESS;
353 }
354
355 EFI_STATUS
356 MmcDetectCard (
357 EFI_MMC_HOST_PROTOCOL *MmcHost
358 )
359 {
360 if (!MmcHost->IsCardPresent (MmcHost)) {
361 return EFI_NO_MEDIA;
362 } else {
363 return EFI_SUCCESS;
364 }
365 }
366
367 EFI_STATUS
368 MmcStopTransmission (
369 EFI_MMC_HOST_PROTOCOL *MmcHost
370 )
371 {
372 EFI_STATUS Status;
373 UINT32 Response[4];
374 // Command 12 - Stop transmission (ends read or write)
375 // Normally only needed for streaming transfers or after error.
376 Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0);
377 if (!EFI_ERROR (Status)) {
378 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1b, Response);
379 }
380 return Status;
381 }
382
383 #define MMCI0_BLOCKLEN 512
384 #define MMCI0_TIMEOUT 10000
385
386 EFI_STATUS
387 MmcIoBlocks (
388 IN EFI_BLOCK_IO_PROTOCOL *This,
389 IN UINTN Transfer,
390 IN UINT32 MediaId,
391 IN EFI_LBA Lba,
392 IN UINTN BufferSize,
393 OUT VOID *Buffer
394 )
395 {
396 UINT32 Response[4];
397 EFI_STATUS Status;
398 UINTN CmdArg;
399 INTN Timeout;
400 UINTN Cmd;
401 MMC_HOST_INSTANCE *MmcHostInstance;
402 EFI_MMC_HOST_PROTOCOL *MmcHost;
403 UINTN BytesRemainingToBeTransfered;
404 UINTN BlockCount;
405
406 BlockCount = 1;
407 MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
408 ASSERT (MmcHostInstance != NULL);
409 MmcHost = MmcHostInstance->MmcHost;
410 ASSERT (MmcHost);
411
412 if (This->Media->MediaId != MediaId) {
413 return EFI_MEDIA_CHANGED;
414 }
415
416 if ((MmcHost == NULL) || (Buffer == NULL)) {
417 return EFI_INVALID_PARAMETER;
418 }
419
420 // Check if a Card is Present
421 if (!MmcHostInstance->BlockIo.Media->MediaPresent) {
422 return EFI_NO_MEDIA;
423 }
424
425 // All blocks must be within the device
426 if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)) {
427 return EFI_INVALID_PARAMETER;
428 }
429
430 if ((Transfer == MMC_IOBLOCKS_WRITE) && (This->Media->ReadOnly == TRUE)) {
431 return EFI_WRITE_PROTECTED;
432 }
433
434 // Reading 0 Byte is valid
435 if (BufferSize == 0) {
436 return EFI_SUCCESS;
437 }
438
439 // The buffer size must be an exact multiple of the block size
440 if ((BufferSize % This->Media->BlockSize) != 0) {
441 return EFI_BAD_BUFFER_SIZE;
442 }
443
444 // Check the alignment
445 if ((This->Media->IoAlign > 2) && (((UINTN)Buffer & (This->Media->IoAlign - 1)) != 0)) {
446 return EFI_INVALID_PARAMETER;
447 }
448
449 BytesRemainingToBeTransfered = BufferSize;
450 while (BytesRemainingToBeTransfered > 0) {
451
452 // Check if the Card is in Ready status
453 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
454 Response[0] = 0;
455 Timeout = 20;
456 while( (!(Response[0] & MMC_R0_READY_FOR_DATA))
457 && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
458 && Timeout--) {
459 Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
460 if (!EFI_ERROR (Status)) {
461 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
462 }
463 }
464
465 if (0 == Timeout) {
466 DEBUG ((EFI_D_ERROR, "The Card is busy\n"));
467 return EFI_NOT_READY;
468 }
469
470 //Set command argument based on the card access mode (Byte mode or Block mode)
471 if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {
472 CmdArg = Lba;
473 } else {
474 CmdArg = Lba * This->Media->BlockSize;
475 }
476
477 if (Transfer == MMC_IOBLOCKS_READ) {
478 // Read a single block
479 Cmd = MMC_CMD17;
480 } else {
481 // Write a single block
482 Cmd = MMC_CMD24;
483 }
484 Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
485 if (EFI_ERROR (Status)) {
486 DEBUG ((EFI_D_ERROR, "MmcIoBlocks(MMC_CMD%d): Error %r\n", Cmd, Status));
487 return Status;
488 }
489
490 if (Transfer == MMC_IOBLOCKS_READ) {
491 // Read one block of Data
492 Status = MmcHost->ReadBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
493 if (EFI_ERROR (Status)) {
494 DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Read Block Data and Status = %r\n", Status));
495 MmcStopTransmission (MmcHost);
496 return Status;
497 }
498 Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);
499 if (EFI_ERROR (Status)) {
500 DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcProgrammingState\n"));
501 return Status;
502 }
503 } else {
504 // Write one block of Data
505 Status = MmcHost->WriteBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
506 if (EFI_ERROR (Status)) {
507 DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Write Block Data and Status = %r\n", Status));
508 MmcStopTransmission (MmcHost);
509 return Status;
510 }
511 }
512
513 // Command 13 - Read status and wait for programming to complete (return to tran)
514 Timeout = MMCI0_TIMEOUT;
515 CmdArg = MmcHostInstance->CardInfo.RCA << 16;
516 Response[0] = 0;
517 while( (!(Response[0] & MMC_R0_READY_FOR_DATA))
518 && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)
519 && Timeout--) {
520 Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);
521 if (!EFI_ERROR (Status)) {
522 MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);
523 if ((Response[0] & MMC_R0_READY_FOR_DATA)) {
524 break; // Prevents delay once finished
525 }
526 }
527 NanoSecondDelay (100);
528 }
529
530 Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
531 if (EFI_ERROR (Status)) {
532 DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));
533 return Status;
534 }
535
536 BytesRemainingToBeTransfered -= This->Media->BlockSize;
537 Lba += BlockCount;
538 Buffer = (UINT8 *)Buffer + This->Media->BlockSize;
539 }
540
541 return EFI_SUCCESS;
542 }
543
544 EFI_STATUS
545 EFIAPI
546 MmcReadBlocks (
547 IN EFI_BLOCK_IO_PROTOCOL *This,
548 IN UINT32 MediaId,
549 IN EFI_LBA Lba,
550 IN UINTN BufferSize,
551 OUT VOID *Buffer
552 )
553 {
554 return MmcIoBlocks (This, MMC_IOBLOCKS_READ, MediaId, Lba, BufferSize, Buffer);
555 }
556
557 EFI_STATUS
558 EFIAPI
559 MmcWriteBlocks (
560 IN EFI_BLOCK_IO_PROTOCOL *This,
561 IN UINT32 MediaId,
562 IN EFI_LBA Lba,
563 IN UINTN BufferSize,
564 IN VOID *Buffer
565 )
566 {
567 return MmcIoBlocks (This, MMC_IOBLOCKS_WRITE, MediaId, Lba, BufferSize, Buffer);
568 }
569
570 EFI_STATUS
571 EFIAPI
572 MmcFlushBlocks (
573 IN EFI_BLOCK_IO_PROTOCOL *This
574 )
575 {
576 return EFI_SUCCESS;
577 }