1 /** @file 2 Routines that use BIOS to support INT 13 devices. 3 4 Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions 8 of the BSD License which accompanies this distribution. The 9 full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15 **/ 16 17 #include "BiosBlkIo.h" 18 19 // 20 // Module global variables 21 // 22 // 23 // Address packet is a buffer under 1 MB for all version EDD calls 24 // 25 extern EDD_DEVICE_ADDRESS_PACKET *mEddBufferUnder1Mb; 26 27 // 28 // This is a buffer for INT 13h func 48 information 29 // 30 extern BIOS_LEGACY_DRIVE *mLegacyDriverUnder1Mb; 31 32 // 33 // Buffer of 0xFE00 bytes for EDD 1.1 transfer must be under 1 MB 34 // 0xFE00 bytes is the max transfer size supported. 35 // 36 extern VOID *mEdd11Buffer; 37 38 39 /** 40 Initialize block I/O device instance 41 42 @param Dev Instance of block I/O device instance 43 44 @retval TRUE Initialization succeeds. 45 @retval FALSE Initialization fails. 46 47 **/ 48 BOOLEAN 49 BiosInitBlockIo ( 50 IN BIOS_BLOCK_IO_DEV *Dev 51 ) 52 { 53 EFI_BLOCK_IO_PROTOCOL *BlockIo; 54 EFI_BLOCK_IO_MEDIA *BlockMedia; 55 BIOS_LEGACY_DRIVE *Bios; 56 57 BlockIo = &Dev->BlockIo; 58 BlockIo->Media = &Dev->BlockMedia; 59 BlockMedia = BlockIo->Media; 60 Bios = &Dev->Bios; 61 62 if (Int13GetDeviceParameters (Dev, Bios) != 0) { 63 if (Int13Extensions (Dev, Bios) != 0) { 64 BlockMedia->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; 65 BlockMedia->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; 66 67 if ((Bios->Parameters.Flags & EDD_DEVICE_REMOVABLE) == EDD_DEVICE_REMOVABLE) { 68 BlockMedia->RemovableMedia = TRUE; 69 } 70 71 } else { 72 // 73 // Legacy Interfaces 74 // 75 BlockMedia->BlockSize = 512; 76 BlockMedia->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1; 77 } 78 79 DEBUG ((DEBUG_INIT, "BlockSize = %d LastBlock = %d\n", BlockMedia->BlockSize, BlockMedia->LastBlock)); 80 81 BlockMedia->LogicalPartition = FALSE; 82 BlockMedia->WriteCaching = FALSE; 83 84 // 85 // BugBug: Need to set this for removable media devices if they do not 86 // have media present 87 // 88 BlockMedia->ReadOnly = FALSE; 89 BlockMedia->MediaPresent = TRUE; 90 91 BlockIo->Reset = BiosBlockIoReset; 92 BlockIo->FlushBlocks = BiosBlockIoFlushBlocks; 93 94 if (!Bios->ExtendedInt13) { 95 // 96 // Legacy interfaces 97 // 98 BlockIo->ReadBlocks = BiosReadLegacyDrive; 99 BlockIo->WriteBlocks = BiosWriteLegacyDrive; 100 } else if ((Bios->EddVersion == EDD_VERSION_30) && (Bios->Extensions64Bit)) { 101 // 102 // EDD 3.0 Required for Device path, but extended reads are not required. 103 // 104 BlockIo->ReadBlocks = Edd30BiosReadBlocks; 105 BlockIo->WriteBlocks = Edd30BiosWriteBlocks; 106 } else { 107 // 108 // Assume EDD 1.1 - Read and Write functions. 109 // This could be EDD 3.0 without Extensions64Bit being set. 110 // If it's EDD 1.1 this will work, but the device path will not 111 // be correct. This will cause confusion to EFI OS installation. 112 // 113 BlockIo->ReadBlocks = Edd11BiosReadBlocks; 114 BlockIo->WriteBlocks = Edd11BiosWriteBlocks; 115 } 116 117 BlockMedia->LogicalPartition = FALSE; 118 BlockMedia->WriteCaching = FALSE; 119 120 return TRUE; 121 } 122 123 return FALSE; 124 } 125 126 /** 127 Gets parameters of block I/O device. 128 129 @param BiosBlockIoDev Instance of block I/O device. 130 @param Drive Legacy drive. 131 132 @return Result of device parameter retrieval. 133 134 **/ 135 UINTN 136 Int13GetDeviceParameters ( 137 IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, 138 IN BIOS_LEGACY_DRIVE *Drive 139 ) 140 { 141 UINTN CarryFlag; 142 UINT16 Cylinder; 143 EFI_IA32_REGISTER_SET Regs; 144 145 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); 146 147 Regs.H.AH = 0x08; 148 Regs.H.DL = Drive->Number; 149 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 150 DEBUG ((DEBUG_INIT, "Int13GetDeviceParameters: INT 13 08 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH)); 151 if (CarryFlag != 0 || Regs.H.AH != 0x00) { 152 Drive->ErrorCode = Regs.H.AH; 153 return FALSE; 154 } 155 156 if (Drive->Floppy) { 157 if (Regs.H.BL == 0x10) { 158 Drive->AtapiFloppy = TRUE; 159 } else { 160 Drive->MaxHead = Regs.H.DH; 161 Drive->MaxSector = Regs.H.CL; 162 Drive->MaxCylinder = Regs.H.CH; 163 if (Drive->MaxSector == 0) { 164 // 165 // BugBug: You can not trust the Carry flag. 166 // 167 return FALSE; 168 } 169 } 170 } else { 171 Drive->MaxHead = (UINT8) (Regs.H.DH & 0x3f); 172 Cylinder = (UINT16) (((UINT16) Regs.H.DH & 0xc0) << 4); 173 Cylinder = (UINT16) (Cylinder | ((UINT16) Regs.H.CL & 0xc0) << 2); 174 Drive->MaxCylinder = (UINT16) (Cylinder + Regs.H.CH); 175 Drive->MaxSector = (UINT8) (Regs.H.CL & 0x3f); 176 } 177 178 return TRUE; 179 } 180 181 /** 182 Extension of INT13 call. 183 184 @param BiosBlockIoDev Instance of block I/O device. 185 @param Drive Legacy drive. 186 187 @return Result of this extension. 188 189 **/ 190 UINTN 191 Int13Extensions ( 192 IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, 193 IN BIOS_LEGACY_DRIVE *Drive 194 ) 195 { 196 INTN CarryFlag; 197 EFI_IA32_REGISTER_SET Regs; 198 199 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); 200 201 Regs.H.AH = 0x41; 202 Regs.X.BX = 0x55aa; 203 Regs.H.DL = Drive->Number; 204 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 205 DEBUG ((DEBUG_INIT, "Int13Extensions: INT 13 41 DL=%02x : CF=%d BX=%04x\n", Drive->Number, CarryFlag, Regs.X.BX)); 206 if (CarryFlag != 0 || Regs.X.BX != 0xaa55) { 207 Drive->ExtendedInt13 = FALSE; 208 Drive->DriveLockingAndEjecting = FALSE; 209 Drive->Edd = FALSE; 210 return FALSE; 211 } 212 213 Drive->EddVersion = Regs.H.AH; 214 Drive->ExtendedInt13 = (BOOLEAN) ((Regs.X.CX & 0x01) == 0x01); 215 Drive->DriveLockingAndEjecting = (BOOLEAN) ((Regs.X.CX & 0x02) == 0x02); 216 Drive->Edd = (BOOLEAN) ((Regs.X.CX & 0x04) == 0x04); 217 Drive->Extensions64Bit = (BOOLEAN) (Regs.X.CX & 0x08); 218 219 Drive->ParametersValid = (UINT8) GetDriveParameters (BiosBlockIoDev, Drive); 220 return TRUE; 221 } 222 223 /** 224 Gets parameters of legacy drive. 225 226 @param BiosBlockIoDev Instance of block I/O device. 227 @param Drive Legacy drive. 228 229 @return Result of drive parameter retrieval. 230 231 **/ 232 UINTN 233 GetDriveParameters ( 234 IN BIOS_BLOCK_IO_DEV *BiosBlockIoDev, 235 IN BIOS_LEGACY_DRIVE *Drive 236 ) 237 { 238 INTN CarryFlag; 239 EFI_IA32_REGISTER_SET Regs; 240 UINTN PointerMath; 241 242 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); 243 244 Regs.H.AH = 0x48; 245 Regs.H.DL = Drive->Number; 246 247 // 248 // EDD Buffer must be passed in with max buffer size as first entry in the buffer 249 // 250 mLegacyDriverUnder1Mb->Parameters.StructureSize = (UINT16) sizeof (EDD_DRIVE_PARAMETERS); 251 Regs.X.DS = EFI_SEGMENT ((UINTN)(&mLegacyDriverUnder1Mb->Parameters)); 252 Regs.X.SI = EFI_OFFSET ((UINTN)(&mLegacyDriverUnder1Mb->Parameters)); 253 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 254 DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 48 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH)); 255 if (CarryFlag != 0 || Regs.H.AH != 0x00) { 256 Drive->ErrorCode = Regs.H.AH; 257 SetMem (&Drive->Parameters, sizeof (Drive->Parameters), 0xaf); 258 return FALSE; 259 } 260 // 261 // We only have one buffer < 1MB, so copy into our instance data 262 // 263 CopyMem ( 264 &Drive->Parameters, 265 &mLegacyDriverUnder1Mb->Parameters, 266 sizeof (Drive->Parameters) 267 ); 268 269 if (Drive->AtapiFloppy) { 270 // 271 // Sense Media Type 272 // 273 Regs.H.AH = 0x20; 274 Regs.H.DL = Drive->Number; 275 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 276 DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 20 DL=%02x : CF=%d AL=%02x\n", Drive->Number, CarryFlag, Regs.H.AL)); 277 if (CarryFlag != 0) { 278 // 279 // Media not present or unknown media present 280 // 281 if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) { 282 Drive->MaxHead = (UINT8) (Drive->Parameters.MaxHeads - 1); 283 Drive->MaxSector = (UINT8) Drive->Parameters.SectorsPerTrack; 284 ASSERT (Drive->MaxSector != 0); 285 Drive->MaxCylinder = (UINT16) (Drive->Parameters.MaxCylinders - 1); 286 } else { 287 Drive->MaxHead = 0; 288 Drive->MaxSector = 1; 289 Drive->MaxCylinder = 0; 290 } 291 292 } else { 293 // 294 // Media Present 295 // 296 switch (Regs.H.AL) { 297 case 0x03: 298 // 299 // 720 KB 300 // 301 Drive->MaxHead = 1; 302 Drive->MaxSector = 9; 303 Drive->MaxCylinder = 79; 304 break; 305 306 case 0x04: 307 // 308 // 1.44MB 309 // 310 Drive->MaxHead = 1; 311 Drive->MaxSector = 18; 312 Drive->MaxCylinder = 79; 313 break; 314 315 case 0x06: 316 // 317 // 2.88MB 318 // 319 Drive->MaxHead = 1; 320 Drive->MaxSector = 36; 321 Drive->MaxCylinder = 79; 322 break; 323 324 case 0x0C: 325 // 326 // 360 KB 327 // 328 Drive->MaxHead = 1; 329 Drive->MaxSector = 9; 330 Drive->MaxCylinder = 39; 331 break; 332 333 case 0x0D: 334 // 335 // 1.2 MB 336 // 337 Drive->MaxHead = 1; 338 Drive->MaxSector = 15; 339 Drive->MaxCylinder = 79; 340 break; 341 342 case 0x0E: 343 // 344 // Toshiba 3 mode 345 // 346 case 0x0F: 347 // 348 // NEC 3 mode 349 // 350 case 0x10: 351 // 352 // Default Media 353 // 354 if ((Drive->Parameters.Flags & EDD_GEOMETRY_VALID) == EDD_GEOMETRY_VALID) { 355 Drive->MaxHead = (UINT8) (Drive->Parameters.MaxHeads - 1); 356 Drive->MaxSector = (UINT8) Drive->Parameters.SectorsPerTrack; 357 ASSERT (Drive->MaxSector != 0); 358 Drive->MaxCylinder = (UINT16) (Drive->Parameters.MaxCylinders - 1); 359 } else { 360 Drive->MaxHead = 0; 361 Drive->MaxSector = 1; 362 Drive->MaxCylinder = 0; 363 } 364 break; 365 366 default: 367 // 368 // Unknown media type. 369 // 370 Drive->MaxHead = 0; 371 Drive->MaxSector = 1; 372 Drive->MaxCylinder = 0; 373 break; 374 } 375 } 376 377 Drive->Parameters.PhysicalSectors = (Drive->MaxHead + 1) * Drive->MaxSector * (Drive->MaxCylinder + 1); 378 Drive->Parameters.BytesPerSector = 512; 379 } 380 // 381 // This data comes from the BIOS so it may not allways be valid 382 // since the BIOS may reuse this buffer for future accesses 383 // 384 PointerMath = EFI_SEGMENT (Drive->Parameters.Fdpt) << 4; 385 PointerMath += EFI_OFFSET (Drive->Parameters.Fdpt); 386 Drive->FdptPointer = (VOID *) PointerMath; 387 388 return TRUE; 389 } 390 // 391 // Block IO Routines 392 // 393 394 /** 395 Read BufferSize bytes from Lba into Buffer. 396 397 @param This Indicates a pointer to the calling context. 398 @param MediaId Id of the media, changes every time the media is replaced. 399 @param Lba The starting Logical Block Address to read from 400 @param BufferSize Size of Buffer, must be a multiple of device block size. 401 @param Buffer A pointer to the destination buffer for the data. The caller is 402 responsible for either having implicit or explicit ownership of the buffer. 403 404 @retval EFI_SUCCESS The data was read correctly from the device. 405 @retval EFI_DEVICE_ERROR The device reported an error while performing the read. 406 @retval EFI_NO_MEDIA There is no media in the device. 407 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. 408 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. 409 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, 410 or the buffer is not on proper alignment. 411 412 **/ 413 EFI_STATUS 414 EFIAPI 415 Edd30BiosReadBlocks ( 416 IN EFI_BLOCK_IO_PROTOCOL *This, 417 IN UINT32 MediaId, 418 IN EFI_LBA Lba, 419 IN UINTN BufferSize, 420 OUT VOID *Buffer 421 ) 422 { 423 EFI_BLOCK_IO_MEDIA *Media; 424 BIOS_BLOCK_IO_DEV *BiosBlockIoDev; 425 EDD_DEVICE_ADDRESS_PACKET *AddressPacket; 426 // 427 // I exist only for readability 428 // 429 EFI_IA32_REGISTER_SET Regs; 430 UINT64 TransferBuffer; 431 UINTN NumberOfBlocks; 432 UINTN TransferByteSize; 433 UINTN BlockSize; 434 BIOS_LEGACY_DRIVE *Bios; 435 UINTN CarryFlag; 436 UINTN MaxTransferBlocks; 437 EFI_BLOCK_IO_PROTOCOL *BlockIo; 438 439 Media = This->Media; 440 BlockSize = Media->BlockSize; 441 442 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); 443 444 if (MediaId != Media->MediaId) { 445 return EFI_MEDIA_CHANGED; 446 } 447 448 if (Lba > Media->LastBlock) { 449 return EFI_INVALID_PARAMETER; 450 } 451 452 if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { 453 return EFI_INVALID_PARAMETER; 454 } 455 456 if (BufferSize % BlockSize != 0) { 457 return EFI_BAD_BUFFER_SIZE; 458 } 459 460 if (Buffer == NULL) { 461 return EFI_INVALID_PARAMETER; 462 } 463 464 if (BufferSize == 0) { 465 return EFI_SUCCESS; 466 } 467 468 BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); 469 AddressPacket = mEddBufferUnder1Mb; 470 471 MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; 472 473 TransferBuffer = (UINT64)(UINTN) Buffer; 474 for (; BufferSize > 0;) { 475 NumberOfBlocks = BufferSize / BlockSize; 476 NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; 477 // 478 // Max transfer MaxTransferBlocks 479 // 480 AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); 481 AddressPacket->Zero = 0; 482 AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; 483 AddressPacket->Zero2 = 0; 484 AddressPacket->SegOffset = 0xffffffff; 485 AddressPacket->Lba = (UINT64) Lba; 486 AddressPacket->TransferBuffer = TransferBuffer; 487 488 Regs.H.AH = 0x42; 489 Regs.H.DL = BiosBlockIoDev->Bios.Number; 490 Regs.X.SI = EFI_OFFSET (AddressPacket); 491 Regs.X.DS = EFI_SEGMENT (AddressPacket); 492 493 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 494 DEBUG ( 495 ( 496 DEBUG_BLKIO, "Edd30BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, 497 CarryFlag, Regs.H.AH 498 ) 499 ); 500 501 Media->MediaPresent = TRUE; 502 if (CarryFlag != 0) { 503 // 504 // Return Error Status 505 // 506 BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; 507 if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { 508 Media->MediaId++; 509 Bios = &BiosBlockIoDev->Bios; 510 if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { 511 if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { 512 Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; 513 Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; 514 } else { 515 ASSERT (FALSE); 516 } 517 518 Media->ReadOnly = FALSE; 519 gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); 520 gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); 521 return EFI_MEDIA_CHANGED; 522 } 523 } 524 525 if (Media->RemovableMedia) { 526 Media->MediaPresent = FALSE; 527 } 528 529 return EFI_DEVICE_ERROR; 530 } 531 532 TransferByteSize = NumberOfBlocks * BlockSize; 533 BufferSize = BufferSize - TransferByteSize; 534 TransferBuffer += TransferByteSize; 535 Lba += NumberOfBlocks; 536 } 537 538 return EFI_SUCCESS; 539 } 540 541 /** 542 Write BufferSize bytes from Lba into Buffer. 543 544 @param This Indicates a pointer to the calling context. 545 @param MediaId The media ID that the write request is for. 546 @param Lba The starting logical block address to be written. The caller is 547 responsible for writing to only legitimate locations. 548 @param BufferSize Size of Buffer, must be a multiple of device block size. 549 @param Buffer A pointer to the source buffer for the data. 550 551 @retval EFI_SUCCESS The data was written correctly to the device. 552 @retval EFI_WRITE_PROTECTED The device can not be written to. 553 @retval EFI_DEVICE_ERROR The device reported an error while performing the write. 554 @retval EFI_NO_MEDIA There is no media in the device. 555 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. 556 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. 557 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, 558 or the buffer is not on proper alignment. 559 560 **/ 561 EFI_STATUS 562 EFIAPI 563 Edd30BiosWriteBlocks ( 564 IN EFI_BLOCK_IO_PROTOCOL *This, 565 IN UINT32 MediaId, 566 IN EFI_LBA Lba, 567 IN UINTN BufferSize, 568 OUT VOID *Buffer 569 ) 570 { 571 EFI_BLOCK_IO_MEDIA *Media; 572 BIOS_BLOCK_IO_DEV *BiosBlockIoDev; 573 EDD_DEVICE_ADDRESS_PACKET *AddressPacket; 574 // 575 // I exist only for readability 576 // 577 EFI_IA32_REGISTER_SET Regs; 578 UINT64 TransferBuffer; 579 UINTN NumberOfBlocks; 580 UINTN TransferByteSize; 581 UINTN BlockSize; 582 BIOS_LEGACY_DRIVE *Bios; 583 UINTN CarryFlag; 584 UINTN MaxTransferBlocks; 585 EFI_BLOCK_IO_PROTOCOL *BlockIo; 586 587 Media = This->Media; 588 BlockSize = Media->BlockSize; 589 590 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); 591 592 if (MediaId != Media->MediaId) { 593 return EFI_MEDIA_CHANGED; 594 } 595 596 if (Lba > Media->LastBlock) { 597 return EFI_DEVICE_ERROR; 598 } 599 600 if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { 601 return EFI_INVALID_PARAMETER; 602 } 603 604 if (BufferSize % BlockSize != 0) { 605 return EFI_BAD_BUFFER_SIZE; 606 } 607 608 if (Buffer == NULL) { 609 return EFI_INVALID_PARAMETER; 610 } 611 612 if (BufferSize == 0) { 613 return EFI_SUCCESS; 614 } 615 616 BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); 617 AddressPacket = mEddBufferUnder1Mb; 618 619 MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; 620 621 TransferBuffer = (UINT64)(UINTN) Buffer; 622 for (; BufferSize > 0;) { 623 NumberOfBlocks = BufferSize / BlockSize; 624 NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; 625 // 626 // Max transfer MaxTransferBlocks 627 // 628 AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); 629 AddressPacket->Zero = 0; 630 AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; 631 AddressPacket->Zero2 = 0; 632 AddressPacket->SegOffset = 0xffffffff; 633 AddressPacket->Lba = (UINT64) Lba; 634 AddressPacket->TransferBuffer = TransferBuffer; 635 636 Regs.H.AH = 0x43; 637 Regs.H.AL = 0x00; 638 // 639 // Write Verify Off 640 // 641 Regs.H.DL = (UINT8) (BiosBlockIoDev->Bios.Number); 642 Regs.X.SI = EFI_OFFSET (AddressPacket); 643 Regs.X.DS = EFI_SEGMENT (AddressPacket); 644 645 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 646 DEBUG ( 647 ( 648 DEBUG_BLKIO, "Edd30BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, 649 CarryFlag, Regs.H.AH 650 ) 651 ); 652 653 Media->MediaPresent = TRUE; 654 if (CarryFlag != 0) { 655 // 656 // Return Error Status 657 // 658 BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; 659 if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { 660 Media->MediaId++; 661 Bios = &BiosBlockIoDev->Bios; 662 if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { 663 if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { 664 Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; 665 Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; 666 } else { 667 ASSERT (FALSE); 668 } 669 670 Media->ReadOnly = FALSE; 671 gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); 672 gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); 673 return EFI_MEDIA_CHANGED; 674 } 675 } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) { 676 Media->ReadOnly = TRUE; 677 return EFI_WRITE_PROTECTED; 678 } 679 680 if (Media->RemovableMedia) { 681 Media->MediaPresent = FALSE; 682 } 683 684 return EFI_DEVICE_ERROR; 685 } 686 687 Media->ReadOnly = FALSE; 688 TransferByteSize = NumberOfBlocks * BlockSize; 689 BufferSize = BufferSize - TransferByteSize; 690 TransferBuffer += TransferByteSize; 691 Lba += NumberOfBlocks; 692 } 693 694 return EFI_SUCCESS; 695 } 696 697 /** 698 Flush the Block Device. 699 700 @param This Indicates a pointer to the calling context. 701 702 @retval EFI_SUCCESS All outstanding data was written to the device 703 @retval EFI_DEVICE_ERROR The device reported an error while writting back the data 704 @retval EFI_NO_MEDIA There is no media in the device. 705 706 **/ 707 EFI_STATUS 708 EFIAPI 709 BiosBlockIoFlushBlocks ( 710 IN EFI_BLOCK_IO_PROTOCOL *This 711 ) 712 { 713 return EFI_SUCCESS; 714 } 715 716 /** 717 Reset the Block Device. 718 719 @param This Indicates a pointer to the calling context. 720 @param ExtendedVerification Driver may perform diagnostics on reset. 721 722 @retval EFI_SUCCESS The device was reset. 723 @retval EFI_DEVICE_ERROR The device is not functioning properly and could 724 not be reset. 725 726 **/ 727 EFI_STATUS 728 EFIAPI 729 BiosBlockIoReset ( 730 IN EFI_BLOCK_IO_PROTOCOL *This, 731 IN BOOLEAN ExtendedVerification 732 ) 733 { 734 BIOS_BLOCK_IO_DEV *BiosBlockIoDev; 735 EFI_IA32_REGISTER_SET Regs; 736 UINTN CarryFlag; 737 738 BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); 739 740 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); 741 742 Regs.H.AH = 0x00; 743 Regs.H.DL = BiosBlockIoDev->Bios.Number; 744 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 745 DEBUG ( 746 ( 747 DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag, 748 Regs.H.AH 749 ) 750 ); 751 if (CarryFlag != 0) { 752 if (Regs.H.AL == BIOS_RESET_FAILED) { 753 Regs.H.AH = 0x00; 754 Regs.H.DL = BiosBlockIoDev->Bios.Number; 755 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 756 DEBUG ( 757 ( 758 DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag, 759 Regs.H.AH 760 ) 761 ); 762 if (CarryFlag != 0) { 763 BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; 764 return EFI_DEVICE_ERROR; 765 } 766 } 767 } 768 769 return EFI_SUCCESS; 770 } 771 // 772 // 773 // These functions need to double buffer all data under 1MB! 774 // 775 // 776 777 /** 778 Read BufferSize bytes from Lba into Buffer. 779 780 @param This Indicates a pointer to the calling context. 781 @param MediaId Id of the media, changes every time the media is replaced. 782 @param Lba The starting Logical Block Address to read from 783 @param BufferSize Size of Buffer, must be a multiple of device block size. 784 @param Buffer A pointer to the destination buffer for the data. The caller is 785 responsible for either having implicit or explicit ownership of the buffer. 786 787 @retval EFI_SUCCESS The data was read correctly from the device. 788 @retval EFI_DEVICE_ERROR The device reported an error while performing the read. 789 @retval EFI_NO_MEDIA There is no media in the device. 790 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. 791 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. 792 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, 793 or the buffer is not on proper alignment. 794 795 **/ 796 EFI_STATUS 797 EFIAPI 798 Edd11BiosReadBlocks ( 799 IN EFI_BLOCK_IO_PROTOCOL *This, 800 IN UINT32 MediaId, 801 IN EFI_LBA Lba, 802 IN UINTN BufferSize, 803 OUT VOID *Buffer 804 ) 805 { 806 EFI_BLOCK_IO_MEDIA *Media; 807 BIOS_BLOCK_IO_DEV *BiosBlockIoDev; 808 EDD_DEVICE_ADDRESS_PACKET *AddressPacket; 809 // 810 // I exist only for readability 811 // 812 EFI_IA32_REGISTER_SET Regs; 813 UINT64 TransferBuffer; 814 UINTN NumberOfBlocks; 815 UINTN TransferByteSize; 816 UINTN BlockSize; 817 BIOS_LEGACY_DRIVE *Bios; 818 UINTN CarryFlag; 819 UINTN MaxTransferBlocks; 820 EFI_BLOCK_IO_PROTOCOL *BlockIo; 821 822 Media = This->Media; 823 BlockSize = Media->BlockSize; 824 825 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); 826 827 if (MediaId != Media->MediaId) { 828 return EFI_MEDIA_CHANGED; 829 } 830 831 if (Lba > Media->LastBlock) { 832 return EFI_INVALID_PARAMETER; 833 } 834 835 if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { 836 return EFI_INVALID_PARAMETER; 837 } 838 839 if (BufferSize % BlockSize != 0) { 840 return EFI_BAD_BUFFER_SIZE; 841 } 842 843 if (Buffer == NULL) { 844 return EFI_INVALID_PARAMETER; 845 } 846 847 if (BufferSize == 0) { 848 return EFI_SUCCESS; 849 } 850 851 BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); 852 AddressPacket = mEddBufferUnder1Mb; 853 854 MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; 855 856 TransferBuffer = (UINT64)(UINTN) mEdd11Buffer; 857 for (; BufferSize > 0;) { 858 NumberOfBlocks = BufferSize / BlockSize; 859 NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; 860 // 861 // Max transfer MaxTransferBlocks 862 // 863 AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); 864 AddressPacket->Zero = 0; 865 AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; 866 AddressPacket->Zero2 = 0; 867 // 868 // TransferBuffer has been 4KB alignment. Normalize TransferBuffer to make offset as 0 in seg:offset 869 // format to transfer maximum 127 blocks of data. 870 // Otherwise when offset adding data size exceeds 0xFFFF, if OpROM does not normalize TransferBuffer, 871 // INT13 function 42H will return data boundary error 09H. 872 // 873 AddressPacket->SegOffset = (UINT32) LShiftU64 (RShiftU64(TransferBuffer, 4), 16); 874 AddressPacket->Lba = (UINT64) Lba; 875 876 Regs.H.AH = 0x42; 877 Regs.H.DL = BiosBlockIoDev->Bios.Number; 878 Regs.X.SI = EFI_OFFSET (AddressPacket); 879 Regs.X.DS = EFI_SEGMENT (AddressPacket); 880 881 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 882 DEBUG ( 883 ( 884 DEBUG_BLKIO, "Edd11BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x : LBA 0x%lx Block(s) %0d \n", 885 BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks 886 ) 887 ); 888 Media->MediaPresent = TRUE; 889 if (CarryFlag != 0) { 890 // 891 // Return Error Status 892 // 893 BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; 894 if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { 895 Media->MediaId++; 896 Bios = &BiosBlockIoDev->Bios; 897 if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { 898 if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { 899 Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; 900 Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; 901 } else { 902 ASSERT (FALSE); 903 } 904 905 Media->ReadOnly = FALSE; 906 gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); 907 gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); 908 return EFI_MEDIA_CHANGED; 909 } 910 } 911 912 if (Media->RemovableMedia) { 913 Media->MediaPresent = FALSE; 914 } 915 916 return EFI_DEVICE_ERROR; 917 } 918 919 TransferByteSize = NumberOfBlocks * BlockSize; 920 CopyMem (Buffer, (VOID *) (UINTN) TransferBuffer, TransferByteSize); 921 BufferSize = BufferSize - TransferByteSize; 922 Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); 923 Lba += NumberOfBlocks; 924 } 925 926 return EFI_SUCCESS; 927 } 928 929 /** 930 Write BufferSize bytes from Lba into Buffer. 931 932 @param This Indicates a pointer to the calling context. 933 @param MediaId The media ID that the write request is for. 934 @param Lba The starting logical block address to be written. The caller is 935 responsible for writing to only legitimate locations. 936 @param BufferSize Size of Buffer, must be a multiple of device block size. 937 @param Buffer A pointer to the source buffer for the data. 938 939 @retval EFI_SUCCESS The data was written correctly to the device. 940 @retval EFI_WRITE_PROTECTED The device can not be written to. 941 @retval EFI_DEVICE_ERROR The device reported an error while performing the write. 942 @retval EFI_NO_MEDIA There is no media in the device. 943 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. 944 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. 945 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, 946 or the buffer is not on proper alignment. 947 948 **/ 949 EFI_STATUS 950 EFIAPI 951 Edd11BiosWriteBlocks ( 952 IN EFI_BLOCK_IO_PROTOCOL *This, 953 IN UINT32 MediaId, 954 IN EFI_LBA Lba, 955 IN UINTN BufferSize, 956 OUT VOID *Buffer 957 ) 958 { 959 EFI_BLOCK_IO_MEDIA *Media; 960 BIOS_BLOCK_IO_DEV *BiosBlockIoDev; 961 EDD_DEVICE_ADDRESS_PACKET *AddressPacket; 962 // 963 // I exist only for readability 964 // 965 EFI_IA32_REGISTER_SET Regs; 966 UINT64 TransferBuffer; 967 UINTN NumberOfBlocks; 968 UINTN TransferByteSize; 969 UINTN BlockSize; 970 BIOS_LEGACY_DRIVE *Bios; 971 UINTN CarryFlag; 972 UINTN MaxTransferBlocks; 973 EFI_BLOCK_IO_PROTOCOL *BlockIo; 974 975 Media = This->Media; 976 BlockSize = Media->BlockSize; 977 978 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); 979 980 if (MediaId != Media->MediaId) { 981 return EFI_MEDIA_CHANGED; 982 } 983 984 if (Lba > Media->LastBlock) { 985 return EFI_INVALID_PARAMETER; 986 } 987 988 if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { 989 return EFI_INVALID_PARAMETER; 990 } 991 992 if (BufferSize % BlockSize != 0) { 993 return EFI_BAD_BUFFER_SIZE; 994 } 995 996 if (Buffer == NULL) { 997 return EFI_INVALID_PARAMETER; 998 } 999 1000 if (BufferSize == 0) { 1001 return EFI_SUCCESS; 1002 } 1003 1004 BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); 1005 AddressPacket = mEddBufferUnder1Mb; 1006 1007 MaxTransferBlocks = MAX_EDD11_XFER / BlockSize; 1008 1009 TransferBuffer = (UINT64)(UINTN) mEdd11Buffer; 1010 for (; BufferSize > 0;) { 1011 NumberOfBlocks = BufferSize / BlockSize; 1012 NumberOfBlocks = NumberOfBlocks > MaxTransferBlocks ? MaxTransferBlocks : NumberOfBlocks; 1013 // 1014 // Max transfer MaxTransferBlocks 1015 // 1016 AddressPacket->PacketSizeInBytes = (UINT8) sizeof (EDD_DEVICE_ADDRESS_PACKET); 1017 AddressPacket->Zero = 0; 1018 AddressPacket->NumberOfBlocks = (UINT8) NumberOfBlocks; 1019 AddressPacket->Zero2 = 0; 1020 // 1021 // TransferBuffer has been 4KB alignment. Normalize TransferBuffer to make offset as 0 in seg:offset 1022 // format to transfer maximum 127 blocks of data. 1023 // Otherwise when offset adding data size exceeds 0xFFFF, if OpROM does not normalize TransferBuffer, 1024 // INT13 function 42H will return data boundary error 09H. 1025 // 1026 AddressPacket->SegOffset = (UINT32) LShiftU64 (RShiftU64(TransferBuffer, 4), 16); 1027 AddressPacket->Lba = (UINT64) Lba; 1028 1029 Regs.H.AH = 0x43; 1030 Regs.H.AL = 0x00; 1031 // 1032 // Write Verify disable 1033 // 1034 Regs.H.DL = BiosBlockIoDev->Bios.Number; 1035 Regs.X.SI = EFI_OFFSET (AddressPacket); 1036 Regs.X.DS = EFI_SEGMENT (AddressPacket); 1037 1038 TransferByteSize = NumberOfBlocks * BlockSize; 1039 CopyMem ((VOID *) (UINTN) TransferBuffer, Buffer, TransferByteSize); 1040 1041 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 1042 DEBUG ( 1043 ( 1044 DEBUG_BLKIO, "Edd11BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n: LBA 0x%lx Block(s) %0d \n", 1045 BiosBlockIoDev->Bios.Number, CarryFlag, Regs.H.AH, Lba, NumberOfBlocks 1046 ) 1047 ); 1048 Media->MediaPresent = TRUE; 1049 if (CarryFlag != 0) { 1050 // 1051 // Return Error Status 1052 // 1053 BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; 1054 if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { 1055 Media->MediaId++; 1056 Bios = &BiosBlockIoDev->Bios; 1057 if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { 1058 if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { 1059 Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; 1060 Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; 1061 } else { 1062 ASSERT (FALSE); 1063 } 1064 1065 Media->ReadOnly = FALSE; 1066 gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); 1067 gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); 1068 return EFI_MEDIA_CHANGED; 1069 } 1070 } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) { 1071 Media->ReadOnly = TRUE; 1072 return EFI_WRITE_PROTECTED; 1073 } 1074 1075 if (Media->RemovableMedia) { 1076 Media->MediaPresent = FALSE; 1077 } 1078 1079 return EFI_DEVICE_ERROR; 1080 } 1081 1082 Media->ReadOnly = FALSE; 1083 BufferSize = BufferSize - TransferByteSize; 1084 Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); 1085 Lba += NumberOfBlocks; 1086 } 1087 1088 return EFI_SUCCESS; 1089 } 1090 1091 /** 1092 Read BufferSize bytes from Lba into Buffer. 1093 1094 @param This Indicates a pointer to the calling context. 1095 @param MediaId Id of the media, changes every time the media is replaced. 1096 @param Lba The starting Logical Block Address to read from 1097 @param BufferSize Size of Buffer, must be a multiple of device block size. 1098 @param Buffer A pointer to the destination buffer for the data. The caller is 1099 responsible for either having implicit or explicit ownership of the buffer. 1100 1101 @retval EFI_SUCCESS The data was read correctly from the device. 1102 @retval EFI_DEVICE_ERROR The device reported an error while performing the read. 1103 @retval EFI_NO_MEDIA There is no media in the device. 1104 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. 1105 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. 1106 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, 1107 or the buffer is not on proper alignment. 1108 1109 **/ 1110 EFI_STATUS 1111 EFIAPI 1112 BiosReadLegacyDrive ( 1113 IN EFI_BLOCK_IO_PROTOCOL *This, 1114 IN UINT32 MediaId, 1115 IN EFI_LBA Lba, 1116 IN UINTN BufferSize, 1117 OUT VOID *Buffer 1118 ) 1119 { 1120 EFI_BLOCK_IO_MEDIA *Media; 1121 BIOS_BLOCK_IO_DEV *BiosBlockIoDev; 1122 EFI_IA32_REGISTER_SET Regs; 1123 UINTN UpperCylinder; 1124 UINTN Temp; 1125 UINTN Cylinder; 1126 UINTN Head; 1127 UINTN Sector; 1128 UINTN NumberOfBlocks; 1129 UINTN TransferByteSize; 1130 UINTN ShortLba; 1131 UINTN CheckLba; 1132 UINTN BlockSize; 1133 BIOS_LEGACY_DRIVE *Bios; 1134 UINTN CarryFlag; 1135 UINTN Retry; 1136 EFI_BLOCK_IO_PROTOCOL *BlockIo; 1137 1138 Media = This->Media; 1139 BlockSize = Media->BlockSize; 1140 1141 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); 1142 1143 if (MediaId != Media->MediaId) { 1144 return EFI_MEDIA_CHANGED; 1145 } 1146 1147 if (Lba > Media->LastBlock) { 1148 return EFI_INVALID_PARAMETER; 1149 } 1150 1151 if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { 1152 return EFI_INVALID_PARAMETER; 1153 } 1154 1155 if (BufferSize % BlockSize != 0) { 1156 return EFI_BAD_BUFFER_SIZE; 1157 } 1158 1159 if (Buffer == NULL) { 1160 return EFI_INVALID_PARAMETER; 1161 } 1162 1163 if (BufferSize == 0) { 1164 return EFI_SUCCESS; 1165 } 1166 1167 BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); 1168 ShortLba = (UINTN) Lba; 1169 1170 while (BufferSize != 0) { 1171 // 1172 // Compute I/O location in Sector, Head, Cylinder format 1173 // 1174 Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1; 1175 Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector; 1176 Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1); 1177 Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1); 1178 1179 // 1180 // Limit transfer to this Head & Cylinder 1181 // 1182 NumberOfBlocks = BufferSize / BlockSize; 1183 Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1; 1184 NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks; 1185 1186 Retry = 3; 1187 do { 1188 // 1189 // Perform the IO 1190 // 1191 Regs.H.AH = 2; 1192 Regs.H.AL = (UINT8) NumberOfBlocks; 1193 Regs.H.DL = BiosBlockIoDev->Bios.Number; 1194 1195 UpperCylinder = (Cylinder & 0x0f00) >> 2; 1196 1197 CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head; 1198 CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1; 1199 1200 DEBUG ( 1201 (DEBUG_BLKIO, 1202 "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n", 1203 ShortLba, 1204 CheckLba, 1205 Sector, 1206 BiosBlockIoDev->Bios.MaxSector, 1207 Head, 1208 BiosBlockIoDev->Bios.MaxHead, 1209 Cylinder, 1210 UpperCylinder) 1211 ); 1212 ASSERT (CheckLba == ShortLba); 1213 1214 Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)); 1215 Regs.H.DH = (UINT8) (Head & 0x3f); 1216 Regs.H.CH = (UINT8) (Cylinder & 0xff); 1217 1218 Regs.X.BX = EFI_OFFSET (mEdd11Buffer); 1219 Regs.X.ES = EFI_SEGMENT (mEdd11Buffer); 1220 1221 DEBUG ( 1222 (DEBUG_BLKIO, 1223 "INT 13h: AX:(02%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n", 1224 Regs.H.AL, 1225 (UINT8) (Head & 0x3f), 1226 Regs.H.DL, 1227 (UINT8) (Cylinder & 0xff), 1228 (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)), 1229 EFI_OFFSET (mEdd11Buffer), 1230 EFI_SEGMENT (mEdd11Buffer)) 1231 ); 1232 1233 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 1234 DEBUG ( 1235 ( 1236 DEBUG_BLKIO, "BiosReadLegacyDrive: INT 13 02 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, 1237 CarryFlag, Regs.H.AH 1238 ) 1239 ); 1240 Retry--; 1241 } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED); 1242 1243 Media->MediaPresent = TRUE; 1244 if (CarryFlag != 0) { 1245 // 1246 // Return Error Status 1247 // 1248 BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; 1249 if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { 1250 Media->MediaId++; 1251 Bios = &BiosBlockIoDev->Bios; 1252 if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { 1253 // 1254 // If the size of the media changed we need to reset the disk geometry 1255 // 1256 if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { 1257 Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; 1258 Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; 1259 } else { 1260 // 1261 // Legacy Interfaces 1262 // 1263 Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1; 1264 Media->BlockSize = 512; 1265 } 1266 1267 Media->ReadOnly = FALSE; 1268 gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); 1269 gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); 1270 return EFI_MEDIA_CHANGED; 1271 } 1272 } 1273 1274 if (Media->RemovableMedia) { 1275 Media->MediaPresent = FALSE; 1276 } 1277 1278 return EFI_DEVICE_ERROR; 1279 } 1280 1281 TransferByteSize = NumberOfBlocks * BlockSize; 1282 CopyMem (Buffer, mEdd11Buffer, TransferByteSize); 1283 1284 ShortLba = ShortLba + NumberOfBlocks; 1285 BufferSize = BufferSize - TransferByteSize; 1286 Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); 1287 } 1288 1289 return EFI_SUCCESS; 1290 } 1291 1292 /** 1293 Write BufferSize bytes from Lba into Buffer. 1294 1295 @param This Indicates a pointer to the calling context. 1296 @param MediaId The media ID that the write request is for. 1297 @param Lba The starting logical block address to be written. The caller is 1298 responsible for writing to only legitimate locations. 1299 @param BufferSize Size of Buffer, must be a multiple of device block size. 1300 @param Buffer A pointer to the source buffer for the data. 1301 1302 @retval EFI_SUCCESS The data was written correctly to the device. 1303 @retval EFI_WRITE_PROTECTED The device can not be written to. 1304 @retval EFI_DEVICE_ERROR The device reported an error while performing the write. 1305 @retval EFI_NO_MEDIA There is no media in the device. 1306 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. 1307 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. 1308 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, 1309 or the buffer is not on proper alignment. 1310 1311 **/ 1312 EFI_STATUS 1313 EFIAPI 1314 BiosWriteLegacyDrive ( 1315 IN EFI_BLOCK_IO_PROTOCOL *This, 1316 IN UINT32 MediaId, 1317 IN EFI_LBA Lba, 1318 IN UINTN BufferSize, 1319 OUT VOID *Buffer 1320 ) 1321 { 1322 EFI_BLOCK_IO_MEDIA *Media; 1323 BIOS_BLOCK_IO_DEV *BiosBlockIoDev; 1324 EFI_IA32_REGISTER_SET Regs; 1325 UINTN UpperCylinder; 1326 UINTN Temp; 1327 UINTN Cylinder; 1328 UINTN Head; 1329 UINTN Sector; 1330 UINTN NumberOfBlocks; 1331 UINTN TransferByteSize; 1332 UINTN ShortLba; 1333 UINTN CheckLba; 1334 UINTN BlockSize; 1335 BIOS_LEGACY_DRIVE *Bios; 1336 UINTN CarryFlag; 1337 UINTN Retry; 1338 EFI_BLOCK_IO_PROTOCOL *BlockIo; 1339 1340 Media = This->Media; 1341 BlockSize = Media->BlockSize; 1342 1343 ZeroMem (&Regs, sizeof (EFI_IA32_REGISTER_SET)); 1344 1345 if (MediaId != Media->MediaId) { 1346 return EFI_MEDIA_CHANGED; 1347 } 1348 1349 if (Lba > Media->LastBlock) { 1350 return EFI_INVALID_PARAMETER; 1351 } 1352 1353 if ((Lba + (BufferSize / BlockSize) - 1) > Media->LastBlock) { 1354 return EFI_INVALID_PARAMETER; 1355 } 1356 1357 if (BufferSize % BlockSize != 0) { 1358 return EFI_BAD_BUFFER_SIZE; 1359 } 1360 1361 if (Buffer == NULL) { 1362 return EFI_INVALID_PARAMETER; 1363 } 1364 1365 if (BufferSize == 0) { 1366 return EFI_SUCCESS; 1367 } 1368 1369 BiosBlockIoDev = BIOS_BLOCK_IO_FROM_THIS (This); 1370 ShortLba = (UINTN) Lba; 1371 1372 while (BufferSize != 0) { 1373 // 1374 // Compute I/O location in Sector, Head, Cylinder format 1375 // 1376 Sector = (ShortLba % BiosBlockIoDev->Bios.MaxSector) + 1; 1377 Temp = ShortLba / BiosBlockIoDev->Bios.MaxSector; 1378 Head = Temp % (BiosBlockIoDev->Bios.MaxHead + 1); 1379 Cylinder = Temp / (BiosBlockIoDev->Bios.MaxHead + 1); 1380 1381 // 1382 // Limit transfer to this Head & Cylinder 1383 // 1384 NumberOfBlocks = BufferSize / BlockSize; 1385 Temp = BiosBlockIoDev->Bios.MaxSector - Sector + 1; 1386 NumberOfBlocks = NumberOfBlocks > Temp ? Temp : NumberOfBlocks; 1387 1388 Retry = 3; 1389 do { 1390 // 1391 // Perform the IO 1392 // 1393 Regs.H.AH = 3; 1394 Regs.H.AL = (UINT8) NumberOfBlocks; 1395 Regs.H.DL = BiosBlockIoDev->Bios.Number; 1396 1397 UpperCylinder = (Cylinder & 0x0f00) >> 2; 1398 1399 CheckLba = Cylinder * (BiosBlockIoDev->Bios.MaxHead + 1) + Head; 1400 CheckLba = CheckLba * BiosBlockIoDev->Bios.MaxSector + Sector - 1; 1401 1402 DEBUG ( 1403 (DEBUG_BLKIO, 1404 "RLD: LBA %x (%x), Sector %x (%x), Head %x (%x), Cyl %x, UCyl %x\n", 1405 ShortLba, 1406 CheckLba, 1407 Sector, 1408 BiosBlockIoDev->Bios.MaxSector, 1409 Head, 1410 BiosBlockIoDev->Bios.MaxHead, 1411 Cylinder, 1412 UpperCylinder) 1413 ); 1414 ASSERT (CheckLba == ShortLba); 1415 1416 Regs.H.CL = (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)); 1417 Regs.H.DH = (UINT8) (Head & 0x3f); 1418 Regs.H.CH = (UINT8) (Cylinder & 0xff); 1419 1420 Regs.X.BX = EFI_OFFSET (mEdd11Buffer); 1421 Regs.X.ES = EFI_SEGMENT (mEdd11Buffer); 1422 1423 TransferByteSize = NumberOfBlocks * BlockSize; 1424 CopyMem (mEdd11Buffer, Buffer, TransferByteSize); 1425 1426 DEBUG ( 1427 (DEBUG_BLKIO, 1428 "INT 13h: AX:(03%02x) DX:(%02x%02x) CX:(%02x%02x) BX:(%04x) ES:(%04x)\n", 1429 Regs.H.AL, 1430 (UINT8) (Head & 0x3f), 1431 Regs.H.DL, 1432 (UINT8) (Cylinder & 0xff), 1433 (UINT8) ((Sector & 0x3f) + (UpperCylinder & 0xff)), 1434 EFI_OFFSET (mEdd11Buffer), 1435 EFI_SEGMENT (mEdd11Buffer)) 1436 ); 1437 1438 CarryFlag = BiosBlockIoDev->LegacyBios->Int86 (BiosBlockIoDev->LegacyBios, 0x13, &Regs); 1439 DEBUG ( 1440 ( 1441 DEBUG_BLKIO, "BiosWriteLegacyDrive: INT 13 03 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, 1442 CarryFlag, Regs.H.AH 1443 ) 1444 ); 1445 Retry--; 1446 } while (CarryFlag != 0 && Retry != 0 && Regs.H.AH != BIOS_DISK_CHANGED); 1447 1448 Media->MediaPresent = TRUE; 1449 if (CarryFlag != 0) { 1450 // 1451 // Return Error Status 1452 // 1453 BiosBlockIoDev->Bios.ErrorCode = Regs.H.AH; 1454 if (BiosBlockIoDev->Bios.ErrorCode == BIOS_DISK_CHANGED) { 1455 Media->MediaId++; 1456 Bios = &BiosBlockIoDev->Bios; 1457 if (Int13GetDeviceParameters (BiosBlockIoDev, Bios) != 0) { 1458 if (Int13Extensions (BiosBlockIoDev, Bios) != 0) { 1459 Media->LastBlock = (EFI_LBA) Bios->Parameters.PhysicalSectors - 1; 1460 Media->BlockSize = (UINT32) Bios->Parameters.BytesPerSector; 1461 } else { 1462 // 1463 // Legacy Interfaces 1464 // 1465 Media->LastBlock = (Bios->MaxHead + 1) * Bios->MaxSector * (Bios->MaxCylinder + 1) - 1; 1466 Media->BlockSize = 512; 1467 } 1468 // 1469 // If the size of the media changed we need to reset the disk geometry 1470 // 1471 Media->ReadOnly = FALSE; 1472 gBS->HandleProtocol (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo); 1473 gBS->ReinstallProtocolInterface (BiosBlockIoDev->Handle, &gEfiBlockIoProtocolGuid, BlockIo, BlockIo); 1474 return EFI_MEDIA_CHANGED; 1475 } 1476 } else if (BiosBlockIoDev->Bios.ErrorCode == BIOS_WRITE_PROTECTED) { 1477 Media->ReadOnly = TRUE; 1478 return EFI_WRITE_PROTECTED; 1479 } 1480 1481 if (Media->RemovableMedia) { 1482 Media->MediaPresent = FALSE; 1483 } 1484 1485 return EFI_DEVICE_ERROR; 1486 } 1487 1488 Media->ReadOnly = FALSE; 1489 ShortLba = ShortLba + NumberOfBlocks; 1490 BufferSize = BufferSize - TransferByteSize; 1491 Buffer = (VOID *) ((UINT8 *) Buffer + TransferByteSize); 1492 } 1493 1494 return EFI_SUCCESS; 1495 } 1496