TianoCore EDK2 master
Loading...
Searching...
No Matches
PeiAtapi.c
Go to the documentation of this file.
1
11#include "UsbBotPeim.h"
12#include "BotPeim.h"
13
14#define MAXSENSEKEY 5
15
29 IN EFI_PEI_SERVICES **PeiServices,
30 IN PEI_BOT_DEVICE *PeiBotDevice
31 )
32{
34 EFI_STATUS Status;
36
37 //
38 // fill command packet
39 //
40 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
41 ZeroMem (&Idata, sizeof (ATAPI_INQUIRY_DATA));
42
43 Packet.Inquiry.opcode = ATA_CMD_INQUIRY;
44 Packet.Inquiry.page_code = 0;
45 Packet.Inquiry.allocation_length = 36;
46
47 //
48 // Send scsi INQUIRY command packet.
49 // According to SCSI Primary Commands-2 spec, host only needs to
50 // retrieve the first 36 bytes for standard INQUIRY data.
51 //
52 Status = PeiAtapiCommand (
53 PeiServices,
54 PeiBotDevice,
55 &Packet,
56 (UINT8)sizeof (ATAPI_PACKET_COMMAND),
57 &Idata,
58 36,
59 EfiUsbDataIn,
60 2000
61 );
62
63 if (EFI_ERROR (Status)) {
64 return EFI_DEVICE_ERROR;
65 }
66
67 if ((Idata.peripheral_type & 0x1f) == 0x05) {
68 PeiBotDevice->DeviceType = USBCDROM;
69 PeiBotDevice->Media.BlockSize = 0x800;
70 PeiBotDevice->Media2.ReadOnly = TRUE;
71 PeiBotDevice->Media2.RemovableMedia = TRUE;
72 PeiBotDevice->Media2.BlockSize = 0x800;
73 } else {
74 PeiBotDevice->DeviceType = USBFLOPPY;
75 PeiBotDevice->Media.BlockSize = 0x200;
76 PeiBotDevice->Media2.ReadOnly = FALSE;
77 PeiBotDevice->Media2.RemovableMedia = TRUE;
78 PeiBotDevice->Media2.BlockSize = 0x200;
79 }
80
81 return EFI_SUCCESS;
82}
83
97 IN EFI_PEI_SERVICES **PeiServices,
98 IN PEI_BOT_DEVICE *PeiBotDevice
99 )
100{
102 EFI_STATUS Status;
103
104 //
105 // fill command packet
106 //
107 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
108 Packet.TestUnitReady.opcode = ATA_CMD_TEST_UNIT_READY;
109
110 //
111 // send command packet
112 //
113 Status = PeiAtapiCommand (
114 PeiServices,
115 PeiBotDevice,
116 &Packet,
117 (UINT8)sizeof (ATAPI_PACKET_COMMAND),
118 NULL,
119 0,
120 EfiUsbNoData,
121 2000
122 );
123
124 if (EFI_ERROR (Status)) {
125 return EFI_DEVICE_ERROR;
126 }
127
128 return EFI_SUCCESS;
129}
130
145 IN EFI_PEI_SERVICES **PeiServices,
146 IN PEI_BOT_DEVICE *PeiBotDevice,
147 OUT UINTN *SenseCounts,
148 IN UINT8 *SenseKeyBuffer
149 )
150{
151 EFI_STATUS Status;
153 UINT8 *Ptr;
154 BOOLEAN SenseReq;
156
157 *SenseCounts = 0;
158
159 //
160 // fill command packet for Request Sense Packet Command
161 //
162 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
163 Packet.RequestSence.opcode = ATA_CMD_REQUEST_SENSE;
164 Packet.RequestSence.allocation_length = (UINT8)sizeof (ATAPI_REQUEST_SENSE_DATA);
165
166 Ptr = SenseKeyBuffer;
167
168 SenseReq = TRUE;
169
170 //
171 // request sense data from device continuously
172 // until no sense data exists in the device.
173 //
174 while (SenseReq) {
175 Sense = (ATAPI_REQUEST_SENSE_DATA *)Ptr;
176
177 //
178 // send out Request Sense Packet Command and get one Sense
179 // data form device.
180 //
181 Status = PeiAtapiCommand (
182 PeiServices,
183 PeiBotDevice,
184 &Packet,
185 (UINT8)sizeof (ATAPI_PACKET_COMMAND),
186 (VOID *)Ptr,
188 EfiUsbDataIn,
189 2000
190 );
191
192 //
193 // failed to get Sense data
194 //
195 if (EFI_ERROR (Status)) {
196 if (*SenseCounts == 0) {
197 return EFI_DEVICE_ERROR;
198 } else {
199 return EFI_SUCCESS;
200 }
201 }
202
203 if (Sense->sense_key != ATA_SK_NO_SENSE) {
204 Ptr += sizeof (ATAPI_REQUEST_SENSE_DATA);
205 //
206 // Ptr is byte based pointer
207 //
208 (*SenseCounts)++;
209
210 if (*SenseCounts == MAXSENSEKEY) {
211 break;
212 }
213 } else {
214 //
215 // when no sense key, skip out the loop
216 //
217 SenseReq = FALSE;
218 }
219 }
220
221 return EFI_SUCCESS;
222}
223
238 IN EFI_PEI_SERVICES **PeiServices,
239 IN PEI_BOT_DEVICE *PeiBotDevice
240 )
241{
242 EFI_STATUS Status;
245 UINT32 LastBlock;
246
247 ZeroMem (&Data, sizeof (ATAPI_READ_CAPACITY_DATA));
248 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
249
250 Packet.Inquiry.opcode = ATA_CMD_READ_CAPACITY;
251
252 //
253 // send command packet
254 //
255 Status = PeiAtapiCommand (
256 PeiServices,
257 PeiBotDevice,
258 &Packet,
259 (UINT8)sizeof (ATAPI_PACKET_COMMAND),
260 (VOID *)&Data,
262 EfiUsbDataIn,
263 2000
264 );
265
266 if (EFI_ERROR (Status)) {
267 return EFI_DEVICE_ERROR;
268 }
269
270 LastBlock = ((UINT32)Data.LastLba3 << 24) | (Data.LastLba2 << 16) | (Data.LastLba1 << 8) | Data.LastLba0;
271
272 if (LastBlock == 0xFFFFFFFF) {
273 DEBUG ((DEBUG_INFO, "The usb device LBA count is larger than 0xFFFFFFFF!\n"));
274 }
275
276 PeiBotDevice->Media.LastBlock = LastBlock;
277 PeiBotDevice->Media.MediaPresent = TRUE;
278
279 PeiBotDevice->Media2.LastBlock = LastBlock;
280 PeiBotDevice->Media2.MediaPresent = TRUE;
281
282 return EFI_SUCCESS;
283}
284
299 IN EFI_PEI_SERVICES **PeiServices,
300 IN PEI_BOT_DEVICE *PeiBotDevice
301 )
302{
303 EFI_STATUS Status;
306 UINT32 LastBlock;
307
308 ZeroMem (&FormatData, sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA));
309 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
310
311 Packet.ReadFormatCapacity.opcode = ATA_CMD_READ_FORMAT_CAPACITY;
312 Packet.ReadFormatCapacity.allocation_length_lo = 12;
313
314 //
315 // send command packet
316 //
317 Status = PeiAtapiCommand (
318 PeiServices,
319 PeiBotDevice,
320 &Packet,
321 (UINT8)sizeof (ATAPI_PACKET_COMMAND),
322 (VOID *)&FormatData,
324 EfiUsbDataIn,
325 2000
326 );
327
328 if (EFI_ERROR (Status)) {
329 return EFI_DEVICE_ERROR;
330 }
331
332 if (FormatData.DesCode == 3) {
333 //
334 // Media is not present
335 //
336 PeiBotDevice->Media.MediaPresent = FALSE;
337 PeiBotDevice->Media.LastBlock = 0;
338 PeiBotDevice->Media2.MediaPresent = FALSE;
339 PeiBotDevice->Media2.LastBlock = 0;
340 } else {
341 LastBlock = ((UINT32)FormatData.LastLba3 << 24) | (FormatData.LastLba2 << 16) | (FormatData.LastLba1 << 8) | FormatData.LastLba0;
342 if (LastBlock == 0xFFFFFFFF) {
343 DEBUG ((DEBUG_INFO, "The usb device LBA count is larger than 0xFFFFFFFF!\n"));
344 }
345
346 PeiBotDevice->Media.LastBlock = LastBlock;
347
348 PeiBotDevice->Media.LastBlock--;
349
350 PeiBotDevice->Media.MediaPresent = TRUE;
351
352 PeiBotDevice->Media2.MediaPresent = TRUE;
353 PeiBotDevice->Media2.LastBlock = PeiBotDevice->Media.LastBlock;
354 }
355
356 return EFI_SUCCESS;
357}
358
376 IN EFI_PEI_SERVICES **PeiServices,
377 IN PEI_BOT_DEVICE *PeiBotDevice,
378 IN VOID *Buffer,
379 IN EFI_PEI_LBA Lba,
380 IN UINTN NumberOfBlocks
381 )
382{
384 ATAPI_READ10_CMD *Read10Packet;
385 UINT16 MaxBlock;
386 UINT32 BlocksRemaining;
387 UINT32 SectorCount;
388 UINT32 Lba32;
389 UINT32 BlockSize;
390 UINT32 ByteCount;
391 VOID *PtrBuffer;
392 EFI_STATUS Status;
393 UINT32 TimeOut;
394
395 //
396 // prepare command packet for the Inquiry Packet Command.
397 //
398 ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
399 Read10Packet = &Packet.Read10;
400 Lba32 = (UINT32)Lba;
401 PtrBuffer = Buffer;
402
403 BlockSize = (UINT32)PeiBotDevice->Media.BlockSize;
404
405 MaxBlock = (UINT16)(MAX_UINT16 / BlockSize);
406 ASSERT (NumberOfBlocks < MAX_UINT32);
407 BlocksRemaining = (UINT32)NumberOfBlocks;
408
409 Status = EFI_SUCCESS;
410 while (BlocksRemaining > 0) {
411 SectorCount = MIN (BlocksRemaining, MaxBlock);
412
413 //
414 // fill the Packet data structure
415 //
416 Read10Packet->opcode = ATA_CMD_READ_10;
417
418 //
419 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
420 // Lba0 is MSB, Lba3 is LSB
421 //
422 Read10Packet->Lba3 = (UINT8)(Lba32 & 0xff);
423 Read10Packet->Lba2 = (UINT8)(Lba32 >> 8);
424 Read10Packet->Lba1 = (UINT8)(Lba32 >> 16);
425 Read10Packet->Lba0 = (UINT8)(Lba32 >> 24);
426
427 //
428 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
429 // TranLen0 is MSB, TranLen is LSB
430 //
431 Read10Packet->TranLen1 = (UINT8)(SectorCount & 0xff);
432 Read10Packet->TranLen0 = (UINT8)(SectorCount >> 8);
433
434 ByteCount = SectorCount * BlockSize;
435
436 TimeOut = SectorCount * 2000;
437
438 //
439 // send command packet
440 //
441 Status = PeiAtapiCommand (
442 PeiServices,
443 PeiBotDevice,
444 &Packet,
445 (UINT8)sizeof (ATAPI_PACKET_COMMAND),
446 (VOID *)PtrBuffer,
447 ByteCount,
448 EfiUsbDataIn,
449 (UINT16)MIN (TimeOut, MAX_UINT16)
450 );
451
452 if (Status != EFI_SUCCESS) {
453 return Status;
454 }
455
456 ASSERT (Lba32 <= (MAX_UINT32-SectorCount));
457 Lba32 += SectorCount;
458 PtrBuffer = (UINT8 *)PtrBuffer + SectorCount * BlockSize;
459 BlocksRemaining = BlocksRemaining - SectorCount;
460 }
461
462 return Status;
463}
464
475BOOLEAN
477 IN ATAPI_REQUEST_SENSE_DATA *SenseData,
478 IN UINTN SenseCounts
479 )
480{
481 ATAPI_REQUEST_SENSE_DATA *SensePtr;
482 UINTN Index;
483 BOOLEAN NoMedia;
484
485 NoMedia = FALSE;
486 SensePtr = SenseData;
487
488 for (Index = 0; Index < SenseCounts; Index++) {
489 switch (SensePtr->sense_key) {
490 case ATA_SK_NOT_READY:
491 switch (SensePtr->addnl_sense_code) {
492 //
493 // if no media, fill IdeDev parameter with specific info.
494 //
495 case ATA_ASC_NO_MEDIA:
496 NoMedia = TRUE;
497 break;
498
499 default:
500 break;
501 }
502
503 break;
504
505 default:
506 break;
507 }
508
509 SensePtr++;
510 }
511
512 return NoMedia;
513}
514
525BOOLEAN
527 IN ATAPI_REQUEST_SENSE_DATA *SenseData,
528 IN UINTN SenseCounts
529 )
530{
531 ATAPI_REQUEST_SENSE_DATA *SensePtr;
532 UINTN Index;
533 BOOLEAN Error;
534
535 SensePtr = SenseData;
536 Error = FALSE;
537
538 for (Index = 0; Index < SenseCounts; Index++) {
539 switch (SensePtr->sense_key) {
540 //
541 // Medium error case
542 //
543 case ATA_SK_MEDIUM_ERROR:
544 switch (SensePtr->addnl_sense_code) {
545 case ATA_ASC_MEDIA_ERR1:
546 //
547 // fall through
548 //
549 case ATA_ASC_MEDIA_ERR2:
550 //
551 // fall through
552 //
553 case ATA_ASC_MEDIA_ERR3:
554 //
555 // fall through
556 //
557 case ATA_ASC_MEDIA_ERR4:
558 Error = TRUE;
559 break;
560
561 default:
562 break;
563 }
564
565 break;
566
567 //
568 // Medium upside-down case
569 //
570 case ATA_SK_NOT_READY:
571 switch (SensePtr->addnl_sense_code) {
572 case ATA_ASC_MEDIA_UPSIDE_DOWN:
573 Error = TRUE;
574 break;
575
576 default:
577 break;
578 }
579
580 break;
581
582 default:
583 break;
584 }
585
586 SensePtr++;
587 }
588
589 return Error;
590}
591
602BOOLEAN
604 IN ATAPI_REQUEST_SENSE_DATA *SenseData,
605 IN UINTN SenseCounts
606 )
607{
608 ATAPI_REQUEST_SENSE_DATA *SensePtr;
609 UINTN Index;
610 BOOLEAN MediaChange;
611
612 MediaChange = FALSE;
613
614 SensePtr = SenseData;
615
616 for (Index = 0; Index < SenseCounts; Index++) {
617 //
618 // catch media change sense key and addition sense data
619 //
620 switch (SensePtr->sense_key) {
621 case ATA_SK_UNIT_ATTENTION:
622 switch (SensePtr->addnl_sense_code) {
623 case ATA_ASC_MEDIA_CHANGE:
624 MediaChange = TRUE;
625 break;
626
627 default:
628 break;
629 }
630
631 break;
632
633 default:
634 break;
635 }
636
637 SensePtr++;
638 }
639
640 return MediaChange;
641}
UINT64 UINTN
#define ATA_CMD_TEST_UNIT_READY
defined from ATA-1
Definition: Atapi.h:490
#define ATA_CMD_REQUEST_SENSE
defined from ATA-4
Definition: Atapi.h:491
#define ATA_CMD_READ_10
defined in ATAPI Removable Rewritable Media Devices
Definition: Atapi.h:495
#define ATA_CMD_READ_CAPACITY
defined in ATAPI Removable Rewritable Media Devices
Definition: Atapi.h:494
#define ATA_CMD_READ_FORMAT_CAPACITY
defined in ATAPI Removable Rewritable Media Devices
Definition: Atapi.h:493
#define ATA_CMD_INQUIRY
defined in ATAPI Removable Rewritable Media Devices
Definition: Atapi.h:492
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS PeiAtapiCommand(IN EFI_PEI_SERVICES **PeiServices, IN PEI_BOT_DEVICE *PeiBotDev, IN VOID *Command, IN UINT8 CommandSize, IN VOID *DataBuffer, IN UINT32 BufferLength, IN EFI_USB_DATA_DIRECTION Direction, IN UINT16 TimeOutInMilliSeconds)
Definition: BotPeim.c:321
#define NULL
Definition: Base.h:319
#define MIN(a, b)
Definition: Base.h:1007
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
UINT64 EFI_PEI_LBA
Definition: BlockIo.h:41
EFI_STATUS PeiUsbReadCapacity(IN EFI_PEI_SERVICES **PeiServices, IN PEI_BOT_DEVICE *PeiBotDevice)
Definition: PeiAtapi.c:237
EFI_STATUS PeiUsbRequestSense(IN EFI_PEI_SERVICES **PeiServices, IN PEI_BOT_DEVICE *PeiBotDevice, OUT UINTN *SenseCounts, IN UINT8 *SenseKeyBuffer)
Definition: PeiAtapi.c:144
EFI_STATUS PeiUsbRead10(IN EFI_PEI_SERVICES **PeiServices, IN PEI_BOT_DEVICE *PeiBotDevice, IN VOID *Buffer, IN EFI_PEI_LBA Lba, IN UINTN NumberOfBlocks)
Definition: PeiAtapi.c:375
EFI_STATUS PeiUsbReadFormattedCapacity(IN EFI_PEI_SERVICES **PeiServices, IN PEI_BOT_DEVICE *PeiBotDevice)
Definition: PeiAtapi.c:298
EFI_STATUS PeiUsbTestUnitReady(IN EFI_PEI_SERVICES **PeiServices, IN PEI_BOT_DEVICE *PeiBotDevice)
Definition: PeiAtapi.c:96
EFI_STATUS PeiUsbInquiry(IN EFI_PEI_SERVICES **PeiServices, IN PEI_BOT_DEVICE *PeiBotDevice)
Definition: PeiAtapi.c:28
BOOLEAN IsNoMedia(IN ATAPI_REQUEST_SENSE_DATA *SenseData, IN UINTN SenseCounts)
Definition: PeiAtapi.c:476
BOOLEAN IsMediaError(IN ATAPI_REQUEST_SENSE_DATA *SenseData, IN UINTN SenseCounts)
Definition: PeiAtapi.c:526
BOOLEAN IsMediaChange(IN ATAPI_REQUEST_SENSE_DATA *SenseData, IN UINTN SenseCounts)
Definition: PeiAtapi.c:603
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
UINT8 page_code
defined in SFF8090i, V6
Definition: Atapi.h:363
UINT8 addnl_sense_code
mandatory
Definition: Atapi.h:295