1 /** @file 2 The helper functions for BlockIo and BlockIo2 protocol. 3 4 Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR> 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 "SdDxe.h" 16 17 /** 18 Nonblocking I/O callback funtion when the event is signaled. 19 20 @param[in] Event The Event this notify function registered to. 21 @param[in] Context Pointer to the context data registered to the 22 Event. 23 24 **/ 25 VOID 26 EFIAPI 27 AsyncIoCallback ( 28 IN EFI_EVENT Event, 29 IN VOID *Context 30 ) 31 { 32 SD_REQUEST *Request; 33 34 gBS->CloseEvent (Event); 35 36 Request = (SD_REQUEST *) Context; 37 38 DEBUG_CODE_BEGIN (); 39 DEBUG ((EFI_D_INFO, "Sd Async Request: CmdIndex[%d] Arg[%08x] %r\n", 40 Request->SdMmcCmdBlk.CommandIndex, Request->SdMmcCmdBlk.CommandArgument, 41 Request->Packet.TransactionStatus)); 42 DEBUG_CODE_END (); 43 44 if (EFI_ERROR (Request->Packet.TransactionStatus)) { 45 Request->Token->TransactionStatus = Request->Packet.TransactionStatus; 46 } 47 48 RemoveEntryList (&Request->Link); 49 50 if (Request->IsEnd) { 51 gBS->SignalEvent (Request->Token->Event); 52 } 53 54 FreePool (Request); 55 } 56 57 /** 58 Send command SET_RELATIVE_ADDRESS to the device to set the device address. 59 60 @param[in] Device A pointer to the SD_DEVICE instance. 61 @param[out] Rca The relative device address to assign. 62 63 @retval EFI_SUCCESS The request is executed successfully. 64 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources. 65 @retval Others The request could not be executed successfully. 66 67 **/ 68 EFI_STATUS 69 SdSetRca ( 70 IN SD_DEVICE *Device, 71 OUT UINT16 *Rca 72 ) 73 { 74 EFI_STATUS Status; 75 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 76 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 77 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 78 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 79 80 PassThru = Device->Private->PassThru; 81 82 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 83 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 84 ZeroMem (&Packet, sizeof (Packet)); 85 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 86 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 87 Packet.Timeout = SD_GENERIC_TIMEOUT; 88 89 SdMmcCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR; 90 SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr; 91 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR6; 92 93 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL); 94 if (!EFI_ERROR (Status)) { 95 DEBUG ((EFI_D_INFO, "Set RCA succeeds with Resp0 = 0x%x\n", SdMmcStatusBlk.Resp0)); 96 *Rca = (UINT16)(SdMmcStatusBlk.Resp0 >> 16); 97 } 98 99 return Status; 100 } 101 102 /** 103 Send command SELECT to the device to select/deselect the device. 104 105 @param[in] Device A pointer to the SD_DEVICE instance. 106 @param[in] Rca The relative device address to use. 107 108 @retval EFI_SUCCESS The request is executed successfully. 109 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources. 110 @retval Others The request could not be executed successfully. 111 112 **/ 113 EFI_STATUS 114 SdSelect ( 115 IN SD_DEVICE *Device, 116 IN UINT16 Rca 117 ) 118 { 119 EFI_STATUS Status; 120 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 121 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 122 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 123 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 124 125 PassThru = Device->Private->PassThru; 126 127 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 128 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 129 ZeroMem (&Packet, sizeof (Packet)); 130 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 131 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 132 Packet.Timeout = SD_GENERIC_TIMEOUT; 133 134 SdMmcCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD; 135 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 136 if (Rca != 0) { 137 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b; 138 } 139 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; 140 141 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL); 142 143 return Status; 144 } 145 146 /** 147 Send command SEND_STATUS to the device to get device status. 148 149 @param[in] Device A pointer to the SD_DEVICE instance. 150 @param[in] Rca The relative device address to use. 151 @param[out] DevStatus The buffer to store the device status. 152 153 @retval EFI_SUCCESS The request is executed successfully. 154 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources. 155 @retval Others The request could not be executed successfully. 156 157 **/ 158 EFI_STATUS 159 SdSendStatus ( 160 IN SD_DEVICE *Device, 161 IN UINT16 Rca, 162 OUT UINT32 *DevStatus 163 ) 164 { 165 EFI_STATUS Status; 166 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 167 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 168 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 169 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 170 171 PassThru = Device->Private->PassThru; 172 173 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 174 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 175 ZeroMem (&Packet, sizeof (Packet)); 176 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 177 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 178 Packet.Timeout = SD_GENERIC_TIMEOUT; 179 180 SdMmcCmdBlk.CommandIndex = SD_SEND_STATUS; 181 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 182 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 183 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; 184 185 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL); 186 if (!EFI_ERROR (Status)) { 187 CopyMem (DevStatus, &SdMmcStatusBlk.Resp0, sizeof (UINT32)); 188 } 189 return Status; 190 } 191 192 /** 193 Send command SEND_CSD to the device to get the CSD register data. 194 195 @param[in] Device A pointer to the SD_DEVICE instance. 196 @param[in] Rca The relative device address to use. 197 @param[out] Csd The buffer to store the SD_CSD register data. 198 199 @retval EFI_SUCCESS The request is executed successfully. 200 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources. 201 @retval Others The request could not be executed successfully. 202 203 **/ 204 EFI_STATUS 205 SdGetCsd ( 206 IN SD_DEVICE *Device, 207 IN UINT16 Rca, 208 OUT SD_CSD *Csd 209 ) 210 { 211 EFI_STATUS Status; 212 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 213 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 214 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 215 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 216 217 PassThru = Device->Private->PassThru; 218 219 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 220 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 221 ZeroMem (&Packet, sizeof (Packet)); 222 ZeroMem (Csd, sizeof (SD_CSD)); 223 224 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 225 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 226 Packet.Timeout = SD_GENERIC_TIMEOUT; 227 228 SdMmcCmdBlk.CommandIndex = SD_SEND_CSD; 229 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 230 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2; 231 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; 232 233 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL); 234 235 if (!EFI_ERROR (Status)) { 236 // 237 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12. 238 // 239 CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1); 240 } 241 242 return Status; 243 } 244 245 /** 246 Send command SEND_CID to the device to get the CID register data. 247 248 @param[in] Device A pointer to the SD_DEVICE instance. 249 @param[in] Rca The relative device address to use. 250 @param[out] Cid The buffer to store the SD_CID register data. 251 252 @retval EFI_SUCCESS The request is executed successfully. 253 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources. 254 @retval Others The request could not be executed successfully. 255 256 **/ 257 EFI_STATUS 258 SdGetCid ( 259 IN SD_DEVICE *Device, 260 IN UINT16 Rca, 261 OUT SD_CID *Cid 262 ) 263 { 264 EFI_STATUS Status; 265 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 266 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 267 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 268 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 269 270 PassThru = Device->Private->PassThru; 271 272 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 273 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 274 ZeroMem (&Packet, sizeof (Packet)); 275 ZeroMem (Cid, sizeof (SD_CID)); 276 277 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 278 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 279 Packet.Timeout = SD_GENERIC_TIMEOUT; 280 281 SdMmcCmdBlk.CommandIndex = SD_SEND_CID; 282 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 283 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2; 284 SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16; 285 286 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL); 287 288 if (!EFI_ERROR (Status)) { 289 // 290 // For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12. 291 // 292 CopyMem (((UINT8*)Cid) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CID) - 1); 293 } 294 295 return Status; 296 } 297 298 /** 299 Read/write single block through sync or async I/O request. 300 301 @param[in] Device A pointer to the SD_DEVICE instance. 302 @param[in] Lba The starting logical block address to be read/written. 303 The caller is responsible for reading/writing to only 304 legitimate locations. 305 @param[in] Buffer A pointer to the destination/source buffer for the data. 306 @param[in] BufferSize Size of Buffer, must be a multiple of device block size. 307 @param[in] IsRead Indicates it is a read or write operation. 308 @param[in] Token A pointer to the token associated with the transaction. 309 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds. 310 This parameter is only meaningful in async I/O request. 311 312 @retval EFI_SUCCESS The request is executed successfully. 313 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources. 314 @retval Others The request could not be executed successfully. 315 316 **/ 317 EFI_STATUS 318 SdRwSingleBlock ( 319 IN SD_DEVICE *Device, 320 IN EFI_LBA Lba, 321 IN VOID *Buffer, 322 IN UINTN BufferSize, 323 IN BOOLEAN IsRead, 324 IN EFI_BLOCK_IO2_TOKEN *Token, 325 IN BOOLEAN IsEnd 326 ) 327 { 328 EFI_STATUS Status; 329 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 330 SD_REQUEST *RwSingleBlkReq; 331 EFI_TPL OldTpl; 332 333 RwSingleBlkReq = NULL; 334 PassThru = Device->Private->PassThru; 335 336 RwSingleBlkReq = AllocateZeroPool (sizeof (SD_REQUEST)); 337 if (RwSingleBlkReq == NULL) { 338 Status = EFI_OUT_OF_RESOURCES; 339 goto Error; 340 } 341 342 RwSingleBlkReq->Signature = SD_REQUEST_SIGNATURE; 343 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 344 InsertTailList (&Device->Queue, &RwSingleBlkReq->Link); 345 gBS->RestoreTPL (OldTpl); 346 RwSingleBlkReq->Packet.SdMmcCmdBlk = &RwSingleBlkReq->SdMmcCmdBlk; 347 RwSingleBlkReq->Packet.SdMmcStatusBlk = &RwSingleBlkReq->SdMmcStatusBlk; 348 // 349 // Calculate timeout value through the below formula. 350 // Timeout = (transfer size) / (2MB/s). 351 // Taking 2MB/s as divisor as it's the lowest transfer speed 352 // above class 2. 353 // Refer to SD Physical Layer Simplified spec section 3.4 for details. 354 // 355 RwSingleBlkReq->Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000; 356 357 if (IsRead) { 358 RwSingleBlkReq->Packet.InDataBuffer = Buffer; 359 RwSingleBlkReq->Packet.InTransferLength = (UINT32)BufferSize; 360 361 RwSingleBlkReq->SdMmcCmdBlk.CommandIndex = SD_READ_SINGLE_BLOCK; 362 RwSingleBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc; 363 RwSingleBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 364 } else { 365 RwSingleBlkReq->Packet.OutDataBuffer = Buffer; 366 RwSingleBlkReq->Packet.OutTransferLength = (UINT32)BufferSize; 367 368 RwSingleBlkReq->SdMmcCmdBlk.CommandIndex = SD_WRITE_SINGLE_BLOCK; 369 RwSingleBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc; 370 RwSingleBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 371 } 372 373 if (Device->SectorAddressing) { 374 RwSingleBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)Lba; 375 } else { 376 RwSingleBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, Device->BlockMedia.BlockSize); 377 } 378 379 RwSingleBlkReq->IsEnd = IsEnd; 380 RwSingleBlkReq->Token = Token; 381 382 if ((Token != NULL) && (Token->Event != NULL)) { 383 Status = gBS->CreateEvent ( 384 EVT_NOTIFY_SIGNAL, 385 TPL_NOTIFY, 386 AsyncIoCallback, 387 RwSingleBlkReq, 388 &RwSingleBlkReq->Event 389 ); 390 if (EFI_ERROR (Status)) { 391 goto Error; 392 } 393 } else { 394 RwSingleBlkReq->Event = NULL; 395 } 396 397 Status = PassThru->PassThru (PassThru, Device->Slot, &RwSingleBlkReq->Packet, RwSingleBlkReq->Event); 398 399 Error: 400 if ((Token != NULL) && (Token->Event != NULL)) { 401 // 402 // For asynchronous operation, only free request and event in error case. 403 // The request and event will be freed in asynchronous callback for success case. 404 // 405 if (EFI_ERROR (Status) && (RwSingleBlkReq != NULL)) { 406 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 407 RemoveEntryList (&RwSingleBlkReq->Link); 408 gBS->RestoreTPL (OldTpl); 409 if (RwSingleBlkReq->Event != NULL) { 410 gBS->CloseEvent (RwSingleBlkReq->Event); 411 } 412 FreePool (RwSingleBlkReq); 413 } 414 } else { 415 // 416 // For synchronous operation, free request whatever the execution result is. 417 // 418 if (RwSingleBlkReq != NULL) { 419 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 420 RemoveEntryList (&RwSingleBlkReq->Link); 421 gBS->RestoreTPL (OldTpl); 422 FreePool (RwSingleBlkReq); 423 } 424 } 425 426 return Status; 427 } 428 429 EFI_STATUS 430 SdStopTrans ( 431 IN SD_DEVICE *Device 432 ) 433 { 434 EFI_STATUS Status; 435 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 436 EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; 437 EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; 438 EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; 439 440 PassThru = Device->Private->PassThru; 441 442 ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); 443 ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); 444 ZeroMem (&Packet, sizeof (Packet)); 445 446 Packet.SdMmcCmdBlk = &SdMmcCmdBlk; 447 Packet.SdMmcStatusBlk = &SdMmcStatusBlk; 448 Packet.Timeout = SD_GENERIC_TIMEOUT; 449 450 SdMmcCmdBlk.CommandIndex = SD_STOP_TRANSMISSION; 451 SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 452 SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b; 453 SdMmcCmdBlk.CommandArgument = 0; 454 455 Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL); 456 return Status; 457 } 458 459 /** 460 Read/write multiple blocks through sync or async I/O request. 461 462 @param[in] Device A pointer to the SD_DEVICE instance. 463 @param[in] Lba The starting logical block address to be read/written. 464 The caller is responsible for reading/writing to only 465 legitimate locations. 466 @param[in] Buffer A pointer to the destination/source buffer for the data. 467 @param[in] BufferSize Size of Buffer, must be a multiple of device block size. 468 @param[in] IsRead Indicates it is a read or write operation. 469 @param[in] Token A pointer to the token associated with the transaction. 470 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds. 471 This parameter is only meaningful in async I/O request. 472 473 @retval EFI_SUCCESS The request is executed successfully. 474 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources. 475 @retval Others The request could not be executed successfully. 476 477 **/ 478 EFI_STATUS 479 SdRwMultiBlocks ( 480 IN SD_DEVICE *Device, 481 IN EFI_LBA Lba, 482 IN VOID *Buffer, 483 IN UINTN BufferSize, 484 IN BOOLEAN IsRead, 485 IN EFI_BLOCK_IO2_TOKEN *Token, 486 IN BOOLEAN IsEnd 487 ) 488 { 489 EFI_STATUS Status; 490 SD_REQUEST *RwMultiBlkReq; 491 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 492 EFI_TPL OldTpl; 493 494 RwMultiBlkReq = NULL; 495 496 PassThru = Device->Private->PassThru; 497 498 RwMultiBlkReq = AllocateZeroPool (sizeof (SD_REQUEST)); 499 if (RwMultiBlkReq == NULL) { 500 Status = EFI_OUT_OF_RESOURCES; 501 goto Error; 502 } 503 504 RwMultiBlkReq->Signature = SD_REQUEST_SIGNATURE; 505 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 506 InsertTailList (&Device->Queue, &RwMultiBlkReq->Link); 507 gBS->RestoreTPL (OldTpl); 508 RwMultiBlkReq->Packet.SdMmcCmdBlk = &RwMultiBlkReq->SdMmcCmdBlk; 509 RwMultiBlkReq->Packet.SdMmcStatusBlk = &RwMultiBlkReq->SdMmcStatusBlk; 510 // 511 // Calculate timeout value through the below formula. 512 // Timeout = (transfer size) / (2MB/s). 513 // Taking 2MB/s as divisor as it's the lowest transfer speed 514 // above class 2. 515 // Refer to SD Physical Layer Simplified spec section 3.4 for details. 516 // 517 RwMultiBlkReq->Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000; 518 519 if (IsRead) { 520 RwMultiBlkReq->Packet.InDataBuffer = Buffer; 521 RwMultiBlkReq->Packet.InTransferLength = (UINT32)BufferSize; 522 523 RwMultiBlkReq->SdMmcCmdBlk.CommandIndex = SD_READ_MULTIPLE_BLOCK; 524 RwMultiBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc; 525 RwMultiBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 526 } else { 527 RwMultiBlkReq->Packet.OutDataBuffer = Buffer; 528 RwMultiBlkReq->Packet.OutTransferLength = (UINT32)BufferSize; 529 530 RwMultiBlkReq->SdMmcCmdBlk.CommandIndex = SD_WRITE_MULTIPLE_BLOCK; 531 RwMultiBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc; 532 RwMultiBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 533 } 534 535 if (Device->SectorAddressing) { 536 RwMultiBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)Lba; 537 } else { 538 RwMultiBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, Device->BlockMedia.BlockSize); 539 } 540 541 RwMultiBlkReq->IsEnd = IsEnd; 542 RwMultiBlkReq->Token = Token; 543 544 if ((Token != NULL) && (Token->Event != NULL)) { 545 Status = gBS->CreateEvent ( 546 EVT_NOTIFY_SIGNAL, 547 TPL_NOTIFY, 548 AsyncIoCallback, 549 RwMultiBlkReq, 550 &RwMultiBlkReq->Event 551 ); 552 if (EFI_ERROR (Status)) { 553 goto Error; 554 } 555 } else { 556 RwMultiBlkReq->Event = NULL; 557 } 558 559 Status = PassThru->PassThru (PassThru, Device->Slot, &RwMultiBlkReq->Packet, RwMultiBlkReq->Event); 560 561 Error: 562 if ((Token != NULL) && (Token->Event != NULL)) { 563 // 564 // For asynchronous operation, only free request and event in error case. 565 // The request and event will be freed in asynchronous callback for success case. 566 // 567 if (EFI_ERROR (Status) && (RwMultiBlkReq != NULL)) { 568 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 569 RemoveEntryList (&RwMultiBlkReq->Link); 570 gBS->RestoreTPL (OldTpl); 571 if (RwMultiBlkReq->Event != NULL) { 572 gBS->CloseEvent (RwMultiBlkReq->Event); 573 } 574 FreePool (RwMultiBlkReq); 575 } 576 } else { 577 // 578 // For synchronous operation, free request whatever the execution result is. 579 // 580 if (RwMultiBlkReq != NULL) { 581 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 582 RemoveEntryList (&RwMultiBlkReq->Link); 583 gBS->RestoreTPL (OldTpl); 584 FreePool (RwMultiBlkReq); 585 } 586 } 587 588 if (EFI_ERROR (Status)) { 589 return Status; 590 } 591 592 Status = SdStopTrans (Device); 593 return Status; 594 } 595 596 /** 597 This function transfers data from/to the sd memory card device. 598 599 @param[in] Device A pointer to the SD_DEVICE instance. 600 @param[in] MediaId The media ID that the read/write request is for. 601 @param[in] Lba The starting logical block address to be read/written. 602 The caller is responsible for reading/writing to only 603 legitimate locations. 604 @param[in, out] Buffer A pointer to the destination/source buffer for the data. 605 @param[in] BufferSize Size of Buffer, must be a multiple of device block size. 606 @param[in] IsRead Indicates it is a read or write operation. 607 @param[in, out] Token A pointer to the token associated with the transaction. 608 609 @retval EFI_SUCCESS The data was read/written correctly to the device. 610 @retval EFI_WRITE_PROTECTED The device can not be read/written to. 611 @retval EFI_DEVICE_ERROR The device reported an error while performing the read/write. 612 @retval EFI_NO_MEDIA There is no media in the device. 613 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. 614 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. 615 @retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid, 616 or the buffer is not on proper alignment. 617 618 **/ 619 EFI_STATUS 620 SdReadWrite ( 621 IN SD_DEVICE *Device, 622 IN UINT32 MediaId, 623 IN EFI_LBA Lba, 624 IN OUT VOID *Buffer, 625 IN UINTN BufferSize, 626 IN BOOLEAN IsRead, 627 IN OUT EFI_BLOCK_IO2_TOKEN *Token 628 ) 629 { 630 EFI_STATUS Status; 631 EFI_BLOCK_IO_MEDIA *Media; 632 UINTN BlockSize; 633 UINTN BlockNum; 634 UINTN IoAlign; 635 UINTN Remaining; 636 UINT32 MaxBlock; 637 BOOLEAN LastRw; 638 639 Status = EFI_SUCCESS; 640 Media = &Device->BlockMedia; 641 LastRw = FALSE; 642 643 if (MediaId != Media->MediaId) { 644 return EFI_MEDIA_CHANGED; 645 } 646 647 if (!IsRead && Media->ReadOnly) { 648 return EFI_WRITE_PROTECTED; 649 } 650 651 // 652 // Check parameters. 653 // 654 if (Buffer == NULL) { 655 return EFI_INVALID_PARAMETER; 656 } 657 658 if (BufferSize == 0) { 659 if ((Token != NULL) && (Token->Event != NULL)) { 660 Token->TransactionStatus = EFI_SUCCESS; 661 gBS->SignalEvent (Token->Event); 662 } 663 return EFI_SUCCESS; 664 } 665 666 BlockSize = Media->BlockSize; 667 if ((BufferSize % BlockSize) != 0) { 668 return EFI_BAD_BUFFER_SIZE; 669 } 670 671 BlockNum = BufferSize / BlockSize; 672 if ((Lba + BlockNum - 1) > Media->LastBlock) { 673 return EFI_INVALID_PARAMETER; 674 } 675 676 IoAlign = Media->IoAlign; 677 if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) { 678 return EFI_INVALID_PARAMETER; 679 } 680 681 if ((Token != NULL) && (Token->Event != NULL)) { 682 Token->TransactionStatus = EFI_SUCCESS; 683 } 684 685 // 686 // Start to execute data transfer. The max block number in single cmd is 65535 blocks. 687 // 688 Remaining = BlockNum; 689 MaxBlock = 0xFFFF; 690 691 while (Remaining > 0) { 692 if (Remaining <= MaxBlock) { 693 BlockNum = Remaining; 694 LastRw = TRUE; 695 } else { 696 BlockNum = MaxBlock; 697 } 698 699 BufferSize = BlockNum * BlockSize; 700 if (BlockNum == 1) { 701 Status = SdRwSingleBlock (Device, Lba, Buffer, BufferSize, IsRead, Token, LastRw); 702 } else { 703 Status = SdRwMultiBlocks (Device, Lba, Buffer, BufferSize, IsRead, Token, LastRw); 704 } 705 if (EFI_ERROR (Status)) { 706 return Status; 707 } 708 DEBUG ((EFI_D_INFO, "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", IsRead ? "Read" : "Write", Lba, BlockNum, Token->Event, Status)); 709 710 Lba += BlockNum; 711 Buffer = (UINT8*)Buffer + BufferSize; 712 Remaining -= BlockNum; 713 } 714 715 return Status; 716 } 717 718 /** 719 Reset the Block Device. 720 721 @param This Indicates a pointer to the calling context. 722 @param ExtendedVerification Driver may perform diagnostics on reset. 723 724 @retval EFI_SUCCESS The device was reset. 725 @retval EFI_DEVICE_ERROR The device is not functioning properly and could 726 not be reset. 727 728 **/ 729 EFI_STATUS 730 EFIAPI 731 SdReset ( 732 IN EFI_BLOCK_IO_PROTOCOL *This, 733 IN BOOLEAN ExtendedVerification 734 ) 735 { 736 EFI_STATUS Status; 737 SD_DEVICE *Device; 738 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 739 740 Device = SD_DEVICE_DATA_FROM_BLKIO (This); 741 742 PassThru = Device->Private->PassThru; 743 Status = PassThru->ResetDevice (PassThru, Device->Slot); 744 if (EFI_ERROR (Status)) { 745 Status = EFI_DEVICE_ERROR; 746 } 747 748 return Status; 749 } 750 751 /** 752 Read BufferSize bytes from Lba into Buffer. 753 754 @param This Indicates a pointer to the calling context. 755 @param MediaId Id of the media, changes every time the media is replaced. 756 @param Lba The starting Logical Block Address to read from 757 @param BufferSize Size of Buffer, must be a multiple of device block size. 758 @param Buffer A pointer to the destination buffer for the data. The caller is 759 responsible for either having implicit or explicit ownership of the buffer. 760 761 @retval EFI_SUCCESS The data was read correctly from the device. 762 @retval EFI_DEVICE_ERROR The device reported an error while performing the read. 763 @retval EFI_NO_MEDIA There is no media in the device. 764 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. 765 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. 766 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, 767 or the buffer is not on proper alignment. 768 769 **/ 770 EFI_STATUS 771 EFIAPI 772 SdReadBlocks ( 773 IN EFI_BLOCK_IO_PROTOCOL *This, 774 IN UINT32 MediaId, 775 IN EFI_LBA Lba, 776 IN UINTN BufferSize, 777 OUT VOID *Buffer 778 ) 779 { 780 EFI_STATUS Status; 781 SD_DEVICE *Device; 782 783 Device = SD_DEVICE_DATA_FROM_BLKIO (This); 784 785 Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, TRUE, NULL); 786 return Status; 787 } 788 789 /** 790 Write BufferSize bytes from Lba into Buffer. 791 792 @param This Indicates a pointer to the calling context. 793 @param MediaId The media ID that the write request is for. 794 @param Lba The starting logical block address to be written. The caller is 795 responsible for writing to only legitimate locations. 796 @param BufferSize Size of Buffer, must be a multiple of device block size. 797 @param Buffer A pointer to the source buffer for the data. 798 799 @retval EFI_SUCCESS The data was written correctly to the device. 800 @retval EFI_WRITE_PROTECTED The device can not be written to. 801 @retval EFI_DEVICE_ERROR The device reported an error while performing the write. 802 @retval EFI_NO_MEDIA There is no media in the device. 803 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. 804 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. 805 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, 806 or the buffer is not on proper alignment. 807 808 **/ 809 EFI_STATUS 810 EFIAPI 811 SdWriteBlocks ( 812 IN EFI_BLOCK_IO_PROTOCOL *This, 813 IN UINT32 MediaId, 814 IN EFI_LBA Lba, 815 IN UINTN BufferSize, 816 IN VOID *Buffer 817 ) 818 { 819 EFI_STATUS Status; 820 SD_DEVICE *Device; 821 822 Device = SD_DEVICE_DATA_FROM_BLKIO (This); 823 824 Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, FALSE, NULL); 825 return Status; 826 } 827 828 /** 829 Flush the Block Device. 830 831 @param This Indicates a pointer to the calling context. 832 833 @retval EFI_SUCCESS All outstanding data was written to the device 834 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data 835 @retval EFI_NO_MEDIA There is no media in the device. 836 837 **/ 838 EFI_STATUS 839 EFIAPI 840 SdFlushBlocks ( 841 IN EFI_BLOCK_IO_PROTOCOL *This 842 ) 843 { 844 // 845 // return directly 846 // 847 return EFI_SUCCESS; 848 } 849 850 /** 851 Reset the Block Device. 852 853 @param[in] This Indicates a pointer to the calling context. 854 @param[in] ExtendedVerification Driver may perform diagnostics on reset. 855 856 @retval EFI_SUCCESS The device was reset. 857 @retval EFI_DEVICE_ERROR The device is not functioning properly and could 858 not be reset. 859 860 **/ 861 EFI_STATUS 862 EFIAPI 863 SdResetEx ( 864 IN EFI_BLOCK_IO2_PROTOCOL *This, 865 IN BOOLEAN ExtendedVerification 866 ) 867 { 868 SD_DEVICE *Device; 869 LIST_ENTRY *Link; 870 LIST_ENTRY *NextLink; 871 SD_REQUEST *Request; 872 EFI_TPL OldTpl; 873 874 Device = SD_DEVICE_DATA_FROM_BLKIO2 (This); 875 876 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 877 for (Link = GetFirstNode (&Device->Queue); 878 !IsNull (&Device->Queue, Link); 879 Link = NextLink) { 880 NextLink = GetNextNode (&Device->Queue, Link); 881 RemoveEntryList (Link); 882 883 Request = SD_REQUEST_FROM_LINK (Link); 884 885 gBS->CloseEvent (Request->Event); 886 Request->Token->TransactionStatus = EFI_ABORTED; 887 888 if (Request->IsEnd) { 889 gBS->SignalEvent (Request->Token->Event); 890 } 891 892 FreePool (Request); 893 } 894 gBS->RestoreTPL (OldTpl); 895 896 return EFI_SUCCESS; 897 } 898 899 /** 900 Read BufferSize bytes from Lba into Buffer. 901 902 @param[in] This Indicates a pointer to the calling context. 903 @param[in] MediaId Id of the media, changes every time the media is replaced. 904 @param[in] Lba The starting Logical Block Address to read from. 905 @param[in, out] Token A pointer to the token associated with the transaction. 906 @param[in] BufferSize Size of Buffer, must be a multiple of device block size. 907 @param[out] Buffer A pointer to the destination buffer for the data. The caller is 908 responsible for either having implicit or explicit ownership of the buffer. 909 910 @retval EFI_SUCCESS The read request was queued if Event is not NULL. 911 The data was read correctly from the device if 912 the Event is NULL. 913 @retval EFI_DEVICE_ERROR The device reported an error while performing 914 the read. 915 @retval EFI_NO_MEDIA There is no media in the device. 916 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. 917 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the 918 intrinsic block size of the device. 919 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, 920 or the buffer is not on proper alignment. 921 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack 922 of resources. 923 924 **/ 925 EFI_STATUS 926 EFIAPI 927 SdReadBlocksEx ( 928 IN EFI_BLOCK_IO2_PROTOCOL *This, 929 IN UINT32 MediaId, 930 IN EFI_LBA Lba, 931 IN OUT EFI_BLOCK_IO2_TOKEN *Token, 932 IN UINTN BufferSize, 933 OUT VOID *Buffer 934 ) 935 { 936 EFI_STATUS Status; 937 SD_DEVICE *Device; 938 939 Device = SD_DEVICE_DATA_FROM_BLKIO2 (This); 940 941 Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, TRUE, Token); 942 return Status; 943 } 944 945 /** 946 Write BufferSize bytes from Lba into Buffer. 947 948 @param[in] This Indicates a pointer to the calling context. 949 @param[in] MediaId The media ID that the write request is for. 950 @param[in] Lba The starting logical block address to be written. The 951 caller is responsible for writing to only legitimate 952 locations. 953 @param[in, out] Token A pointer to the token associated with the transaction. 954 @param[in] BufferSize Size of Buffer, must be a multiple of device block size. 955 @param[in] Buffer A pointer to the source buffer for the data. 956 957 @retval EFI_SUCCESS The data was written correctly to the device. 958 @retval EFI_WRITE_PROTECTED The device can not be written to. 959 @retval EFI_DEVICE_ERROR The device reported an error while performing the write. 960 @retval EFI_NO_MEDIA There is no media in the device. 961 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. 962 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. 963 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, 964 or the buffer is not on proper alignment. 965 966 **/ 967 EFI_STATUS 968 EFIAPI 969 SdWriteBlocksEx ( 970 IN EFI_BLOCK_IO2_PROTOCOL *This, 971 IN UINT32 MediaId, 972 IN EFI_LBA Lba, 973 IN OUT EFI_BLOCK_IO2_TOKEN *Token, 974 IN UINTN BufferSize, 975 IN VOID *Buffer 976 ) 977 { 978 EFI_STATUS Status; 979 SD_DEVICE *Device; 980 981 Device = SD_DEVICE_DATA_FROM_BLKIO2 (This); 982 983 Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, FALSE, Token); 984 return Status; 985 } 986 987 /** 988 Flush the Block Device. 989 990 @param[in] This Indicates a pointer to the calling context. 991 @param[in, out] Token A pointer to the token associated with the transaction. 992 993 @retval EFI_SUCCESS All outstanding data was written to the device 994 @retval EFI_DEVICE_ERROR The device reported an error while writing back the data 995 @retval EFI_NO_MEDIA There is no media in the device. 996 997 **/ 998 EFI_STATUS 999 EFIAPI 1000 SdFlushBlocksEx ( 1001 IN EFI_BLOCK_IO2_PROTOCOL *This, 1002 IN OUT EFI_BLOCK_IO2_TOKEN *Token 1003 ) 1004 { 1005 // 1006 // Signal event and return directly. 1007 // 1008 if (Token != NULL && Token->Event != NULL) { 1009 Token->TransactionStatus = EFI_SUCCESS; 1010 gBS->SignalEvent (Token->Event); 1011 } 1012 1013 return EFI_SUCCESS; 1014 } 1015 1016 /** 1017 Set the erase start address through sync or async I/O request. 1018 1019 @param[in] Device A pointer to the SD_DEVICE instance. 1020 @param[in] StartLba The starting logical block address to be erased. 1021 @param[in] Token A pointer to the token associated with the transaction. 1022 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds. 1023 This parameter is only meaningful in async I/O request. 1024 1025 @retval EFI_SUCCESS The request is executed successfully. 1026 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources. 1027 @retval Others The request could not be executed successfully. 1028 1029 **/ 1030 EFI_STATUS 1031 SdEraseBlockStart ( 1032 IN SD_DEVICE *Device, 1033 IN EFI_LBA StartLba, 1034 IN EFI_BLOCK_IO2_TOKEN *Token, 1035 IN BOOLEAN IsEnd 1036 ) 1037 { 1038 EFI_STATUS Status; 1039 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 1040 SD_REQUEST *EraseBlockStart; 1041 EFI_TPL OldTpl; 1042 1043 EraseBlockStart = NULL; 1044 PassThru = Device->Private->PassThru; 1045 1046 EraseBlockStart = AllocateZeroPool (sizeof (SD_REQUEST)); 1047 if (EraseBlockStart == NULL) { 1048 Status = EFI_OUT_OF_RESOURCES; 1049 goto Error; 1050 } 1051 1052 EraseBlockStart->Signature = SD_REQUEST_SIGNATURE; 1053 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 1054 InsertTailList (&Device->Queue, &EraseBlockStart->Link); 1055 gBS->RestoreTPL (OldTpl); 1056 EraseBlockStart->Packet.SdMmcCmdBlk = &EraseBlockStart->SdMmcCmdBlk; 1057 EraseBlockStart->Packet.SdMmcStatusBlk = &EraseBlockStart->SdMmcStatusBlk; 1058 EraseBlockStart->Packet.Timeout = SD_GENERIC_TIMEOUT; 1059 1060 EraseBlockStart->SdMmcCmdBlk.CommandIndex = SD_ERASE_WR_BLK_START; 1061 EraseBlockStart->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 1062 EraseBlockStart->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 1063 1064 if (Device->SectorAddressing) { 1065 EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)StartLba; 1066 } else { 1067 EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (StartLba, Device->BlockMedia.BlockSize); 1068 } 1069 1070 EraseBlockStart->IsEnd = IsEnd; 1071 EraseBlockStart->Token = Token; 1072 1073 if ((Token != NULL) && (Token->Event != NULL)) { 1074 Status = gBS->CreateEvent ( 1075 EVT_NOTIFY_SIGNAL, 1076 TPL_NOTIFY, 1077 AsyncIoCallback, 1078 EraseBlockStart, 1079 &EraseBlockStart->Event 1080 ); 1081 if (EFI_ERROR (Status)) { 1082 goto Error; 1083 } 1084 } else { 1085 EraseBlockStart->Event = NULL; 1086 } 1087 1088 Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockStart->Packet, EraseBlockStart->Event); 1089 1090 Error: 1091 if ((Token != NULL) && (Token->Event != NULL)) { 1092 // 1093 // For asynchronous operation, only free request and event in error case. 1094 // The request and event will be freed in asynchronous callback for success case. 1095 // 1096 if (EFI_ERROR (Status) && (EraseBlockStart != NULL)) { 1097 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 1098 RemoveEntryList (&EraseBlockStart->Link); 1099 gBS->RestoreTPL (OldTpl); 1100 if (EraseBlockStart->Event != NULL) { 1101 gBS->CloseEvent (EraseBlockStart->Event); 1102 } 1103 FreePool (EraseBlockStart); 1104 } 1105 } else { 1106 // 1107 // For synchronous operation, free request whatever the execution result is. 1108 // 1109 if (EraseBlockStart != NULL) { 1110 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 1111 RemoveEntryList (&EraseBlockStart->Link); 1112 gBS->RestoreTPL (OldTpl); 1113 FreePool (EraseBlockStart); 1114 } 1115 } 1116 1117 return Status; 1118 } 1119 1120 /** 1121 Set the erase end address through sync or async I/O request. 1122 1123 @param[in] Device A pointer to the SD_DEVICE instance. 1124 @param[in] EndLba The ending logical block address to be erased. 1125 @param[in] Token A pointer to the token associated with the transaction. 1126 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds. 1127 This parameter is only meaningful in async I/O request. 1128 1129 @retval EFI_SUCCESS The request is executed successfully. 1130 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources. 1131 @retval Others The request could not be executed successfully. 1132 1133 **/ 1134 EFI_STATUS 1135 SdEraseBlockEnd ( 1136 IN SD_DEVICE *Device, 1137 IN EFI_LBA EndLba, 1138 IN EFI_BLOCK_IO2_TOKEN *Token, 1139 IN BOOLEAN IsEnd 1140 ) 1141 { 1142 EFI_STATUS Status; 1143 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 1144 SD_REQUEST *EraseBlockEnd; 1145 EFI_TPL OldTpl; 1146 1147 EraseBlockEnd = NULL; 1148 PassThru = Device->Private->PassThru; 1149 1150 EraseBlockEnd = AllocateZeroPool (sizeof (SD_REQUEST)); 1151 if (EraseBlockEnd == NULL) { 1152 Status = EFI_OUT_OF_RESOURCES; 1153 goto Error; 1154 } 1155 1156 EraseBlockEnd->Signature = SD_REQUEST_SIGNATURE; 1157 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 1158 InsertTailList (&Device->Queue, &EraseBlockEnd->Link); 1159 gBS->RestoreTPL (OldTpl); 1160 EraseBlockEnd->Packet.SdMmcCmdBlk = &EraseBlockEnd->SdMmcCmdBlk; 1161 EraseBlockEnd->Packet.SdMmcStatusBlk = &EraseBlockEnd->SdMmcStatusBlk; 1162 EraseBlockEnd->Packet.Timeout = SD_GENERIC_TIMEOUT; 1163 1164 EraseBlockEnd->SdMmcCmdBlk.CommandIndex = SD_ERASE_WR_BLK_END; 1165 EraseBlockEnd->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 1166 EraseBlockEnd->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1; 1167 1168 if (Device->SectorAddressing) { 1169 EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)EndLba; 1170 } else { 1171 EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (EndLba, Device->BlockMedia.BlockSize); 1172 } 1173 1174 EraseBlockEnd->IsEnd = IsEnd; 1175 EraseBlockEnd->Token = Token; 1176 1177 if ((Token != NULL) && (Token->Event != NULL)) { 1178 Status = gBS->CreateEvent ( 1179 EVT_NOTIFY_SIGNAL, 1180 TPL_NOTIFY, 1181 AsyncIoCallback, 1182 EraseBlockEnd, 1183 &EraseBlockEnd->Event 1184 ); 1185 if (EFI_ERROR (Status)) { 1186 goto Error; 1187 } 1188 } else { 1189 EraseBlockEnd->Event = NULL; 1190 } 1191 1192 Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockEnd->Packet, EraseBlockEnd->Event); 1193 1194 Error: 1195 if ((Token != NULL) && (Token->Event != NULL)) { 1196 // 1197 // For asynchronous operation, only free request and event in error case. 1198 // The request and event will be freed in asynchronous callback for success case. 1199 // 1200 if (EFI_ERROR (Status) && (EraseBlockEnd != NULL)) { 1201 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 1202 RemoveEntryList (&EraseBlockEnd->Link); 1203 gBS->RestoreTPL (OldTpl); 1204 if (EraseBlockEnd->Event != NULL) { 1205 gBS->CloseEvent (EraseBlockEnd->Event); 1206 } 1207 FreePool (EraseBlockEnd); 1208 } 1209 } else { 1210 // 1211 // For synchronous operation, free request whatever the execution result is. 1212 // 1213 if (EraseBlockEnd != NULL) { 1214 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 1215 RemoveEntryList (&EraseBlockEnd->Link); 1216 gBS->RestoreTPL (OldTpl); 1217 FreePool (EraseBlockEnd); 1218 } 1219 } 1220 1221 return Status; 1222 } 1223 1224 /** 1225 Erase specified blocks through sync or async I/O request. 1226 1227 @param[in] Device A pointer to the SD_DEVICE instance. 1228 @param[in] Token A pointer to the token associated with the transaction. 1229 @param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds. 1230 This parameter is only meaningful in async I/O request. 1231 1232 @retval EFI_SUCCESS The request is executed successfully. 1233 @retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources. 1234 @retval Others The request could not be executed successfully. 1235 1236 **/ 1237 EFI_STATUS 1238 SdEraseBlock ( 1239 IN SD_DEVICE *Device, 1240 IN EFI_BLOCK_IO2_TOKEN *Token, 1241 IN BOOLEAN IsEnd 1242 ) 1243 { 1244 EFI_STATUS Status; 1245 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; 1246 SD_REQUEST *EraseBlock; 1247 EFI_TPL OldTpl; 1248 1249 EraseBlock = NULL; 1250 PassThru = Device->Private->PassThru; 1251 1252 EraseBlock = AllocateZeroPool (sizeof (SD_REQUEST)); 1253 if (EraseBlock == NULL) { 1254 Status = EFI_OUT_OF_RESOURCES; 1255 goto Error; 1256 } 1257 1258 EraseBlock->Signature = SD_REQUEST_SIGNATURE; 1259 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 1260 InsertTailList (&Device->Queue, &EraseBlock->Link); 1261 gBS->RestoreTPL (OldTpl); 1262 EraseBlock->Packet.SdMmcCmdBlk = &EraseBlock->SdMmcCmdBlk; 1263 EraseBlock->Packet.SdMmcStatusBlk = &EraseBlock->SdMmcStatusBlk; 1264 EraseBlock->Packet.Timeout = SD_GENERIC_TIMEOUT; 1265 1266 EraseBlock->SdMmcCmdBlk.CommandIndex = SD_ERASE; 1267 EraseBlock->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; 1268 EraseBlock->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b; 1269 1270 EraseBlock->IsEnd = IsEnd; 1271 EraseBlock->Token = Token; 1272 1273 if ((Token != NULL) && (Token->Event != NULL)) { 1274 Status = gBS->CreateEvent ( 1275 EVT_NOTIFY_SIGNAL, 1276 TPL_NOTIFY, 1277 AsyncIoCallback, 1278 EraseBlock, 1279 &EraseBlock->Event 1280 ); 1281 if (EFI_ERROR (Status)) { 1282 goto Error; 1283 } 1284 } else { 1285 EraseBlock->Event = NULL; 1286 } 1287 1288 Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlock->Packet, EraseBlock->Event); 1289 1290 Error: 1291 if ((Token != NULL) && (Token->Event != NULL)) { 1292 // 1293 // For asynchronous operation, only free request and event in error case. 1294 // The request and event will be freed in asynchronous callback for success case. 1295 // 1296 if (EFI_ERROR (Status) && (EraseBlock != NULL)) { 1297 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 1298 RemoveEntryList (&EraseBlock->Link); 1299 gBS->RestoreTPL (OldTpl); 1300 if (EraseBlock->Event != NULL) { 1301 gBS->CloseEvent (EraseBlock->Event); 1302 } 1303 FreePool (EraseBlock); 1304 } 1305 } else { 1306 // 1307 // For synchronous operation, free request whatever the execution result is. 1308 // 1309 if (EraseBlock != NULL) { 1310 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); 1311 RemoveEntryList (&EraseBlock->Link); 1312 gBS->RestoreTPL (OldTpl); 1313 FreePool (EraseBlock); 1314 } 1315 } 1316 1317 return Status; 1318 } 1319 1320 /** 1321 Erase a specified number of device blocks. 1322 1323 @param[in] This Indicates a pointer to the calling context. 1324 @param[in] MediaId The media ID that the erase request is for. 1325 @param[in] Lba The starting logical block address to be 1326 erased. The caller is responsible for erasing 1327 only legitimate locations. 1328 @param[in, out] Token A pointer to the token associated with the 1329 transaction. 1330 @param[in] Size The size in bytes to be erased. This must be 1331 a multiple of the physical block size of the 1332 device. 1333 1334 @retval EFI_SUCCESS The erase request was queued if Event is not 1335 NULL. The data was erased correctly to the 1336 device if the Event is NULL.to the device. 1337 @retval EFI_WRITE_PROTECTED The device cannot be erased due to write 1338 protection. 1339 @retval EFI_DEVICE_ERROR The device reported an error while attempting 1340 to perform the erase operation. 1341 @retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not 1342 valid. 1343 @retval EFI_NO_MEDIA There is no media in the device. 1344 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. 1345 1346 **/ 1347 EFI_STATUS 1348 EFIAPI 1349 SdEraseBlocks ( 1350 IN EFI_ERASE_BLOCK_PROTOCOL *This, 1351 IN UINT32 MediaId, 1352 IN EFI_LBA Lba, 1353 IN OUT EFI_ERASE_BLOCK_TOKEN *Token, 1354 IN UINTN Size 1355 ) 1356 { 1357 EFI_STATUS Status; 1358 EFI_BLOCK_IO_MEDIA *Media; 1359 UINTN BlockSize; 1360 UINTN BlockNum; 1361 EFI_LBA LastLba; 1362 SD_DEVICE *Device; 1363 1364 Status = EFI_SUCCESS; 1365 Device = SD_DEVICE_DATA_FROM_ERASEBLK (This); 1366 Media = &Device->BlockMedia; 1367 1368 if (MediaId != Media->MediaId) { 1369 return EFI_MEDIA_CHANGED; 1370 } 1371 1372 if (Media->ReadOnly) { 1373 return EFI_WRITE_PROTECTED; 1374 } 1375 1376 // 1377 // Check parameters. 1378 // 1379 BlockSize = Media->BlockSize; 1380 if ((Size % BlockSize) != 0) { 1381 return EFI_INVALID_PARAMETER; 1382 } 1383 1384 BlockNum = Size / BlockSize; 1385 if ((Lba + BlockNum - 1) > Media->LastBlock) { 1386 return EFI_INVALID_PARAMETER; 1387 } 1388 1389 if ((Token != NULL) && (Token->Event != NULL)) { 1390 Token->TransactionStatus = EFI_SUCCESS; 1391 } 1392 1393 LastLba = Lba + BlockNum - 1; 1394 1395 Status = SdEraseBlockStart (Device, Lba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE); 1396 if (EFI_ERROR (Status)) { 1397 return Status; 1398 } 1399 1400 Status = SdEraseBlockEnd (Device, LastLba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE); 1401 if (EFI_ERROR (Status)) { 1402 return Status; 1403 } 1404 1405 Status = SdEraseBlock (Device, (EFI_BLOCK_IO2_TOKEN*)Token, TRUE); 1406 if (EFI_ERROR (Status)) { 1407 return Status; 1408 } 1409 1410 DEBUG ((EFI_D_ERROR, "SdEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", Lba, BlockNum, Token->Event, Status)); 1411 1412 return Status; 1413 } 1414 1415