]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c
7f6cd4daf26796f7320d227acdde074f10b9e6ef
[mirror_edk2.git] / EdkModulePkg / Bus / Usb / UsbMassStorage / Dxe / UsbMassStorage.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 UsbMassStorage.c
15
16 Abstract:
17
18 USB Mass Storage Driver
19
20 Revision History
21
22 --*/
23
24 #include "UsbMassStorage.h"
25 #include "UsbMassStorageHelper.h"
26
27 extern EFI_COMPONENT_NAME_PROTOCOL gUsbMassStorageComponentName;
28
29 //
30 // Prototypes
31 // Driver model protocol interface
32 //
33 EFI_STATUS
34 EFIAPI
35 USBMassStorageDriverBindingEntryPoint (
36 IN EFI_HANDLE ImageHandle,
37 IN EFI_SYSTEM_TABLE *SystemTable
38 );
39
40 EFI_STATUS
41 EFIAPI
42 USBFloppyDriverBindingSupported (
43 IN EFI_DRIVER_BINDING_PROTOCOL *This,
44 IN EFI_HANDLE Controller,
45 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
46 );
47
48 EFI_STATUS
49 EFIAPI
50 USBFloppyDriverBindingStart (
51 IN EFI_DRIVER_BINDING_PROTOCOL *This,
52 IN EFI_HANDLE Controller,
53 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
54 );
55
56 EFI_STATUS
57 EFIAPI
58 USBFloppyDriverBindingStop (
59 IN EFI_DRIVER_BINDING_PROTOCOL *This,
60 IN EFI_HANDLE Controller,
61 IN UINTN NumberOfChildren,
62 IN EFI_HANDLE *ChildHandleBuffer
63 );
64
65 //
66 // Block I/O Protocol Interface
67 //
68 STATIC
69 EFI_STATUS
70 EFIAPI
71 USBFloppyReset (
72 IN EFI_BLOCK_IO_PROTOCOL *This,
73 IN BOOLEAN ExtendedVerification
74 );
75
76 STATIC
77 EFI_STATUS
78 EFIAPI
79 USBFloppyReadBlocks (
80 IN EFI_BLOCK_IO_PROTOCOL *This,
81 IN UINT32 MediaId,
82 IN EFI_LBA LBA,
83 IN UINTN BufferSize,
84 OUT VOID *Buffer
85 );
86
87 STATIC
88 EFI_STATUS
89 EFIAPI
90 USBFloppyWriteBlocks (
91 IN EFI_BLOCK_IO_PROTOCOL *This,
92 IN UINT32 MediaId,
93 IN EFI_LBA LBA,
94 IN UINTN BufferSize,
95 IN VOID *Buffer
96 );
97
98 STATIC
99 EFI_STATUS
100 EFIAPI
101 USBFloppyFlushBlocks (
102 IN EFI_BLOCK_IO_PROTOCOL *This
103 );
104
105 //
106 // USB Floppy Driver Global Variables
107 //
108 EFI_DRIVER_BINDING_PROTOCOL gUSBFloppyDriverBinding = {
109 USBFloppyDriverBindingSupported,
110 USBFloppyDriverBindingStart,
111 USBFloppyDriverBindingStop,
112 0xa,
113 NULL,
114 NULL
115 };
116
117 EFI_STATUS
118 EFIAPI
119 USBFloppyDriverBindingSupported (
120 IN EFI_DRIVER_BINDING_PROTOCOL *This,
121 IN EFI_HANDLE Controller,
122 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
123 )
124 /*++
125
126 Routine Description:
127 Test to see if this driver supports ControllerHandle. Any ControllerHandle
128 that has UsbHcProtocol installed will be supported.
129
130 Arguments:
131 This - Protocol instance pointer.
132 Controller - Handle of device to test
133 RemainingDevicePath - Not used
134
135 Returns:
136 EFI_SUCCESS - This driver supports this device.
137 EFI_UNSUPPORTED - This driver does not support this device.
138
139 --*/
140 {
141 EFI_STATUS OpenStatus;
142 EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;
143
144 //
145 // check whether EFI_USB_ATAPI_PROTOCOL exists, if it does,
146 // then the controller must be a USB Mass Storage Controller
147 //
148 OpenStatus = gBS->OpenProtocol (
149 Controller,
150 &gEfiUsbAtapiProtocolGuid,
151 (VOID **) &AtapiProtocol,
152 This->DriverBindingHandle,
153 Controller,
154 EFI_OPEN_PROTOCOL_BY_DRIVER
155 );
156 if (EFI_ERROR (OpenStatus)) {
157 return OpenStatus;
158 }
159
160 gBS->CloseProtocol (
161 Controller,
162 &gEfiUsbAtapiProtocolGuid,
163 This->DriverBindingHandle,
164 Controller
165 );
166
167 return EFI_SUCCESS;
168 }
169
170 EFI_STATUS
171 EFIAPI
172 USBFloppyDriverBindingStart (
173 IN EFI_DRIVER_BINDING_PROTOCOL *This,
174 IN EFI_HANDLE Controller,
175 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
176 )
177 /*++
178
179 Routine Description:
180 Starting the Usb Bus Driver
181
182 Arguments:
183 This - Protocol instance pointer.
184 Controller - Handle of device to test
185 RemainingDevicePath - Not used
186
187 Returns:
188 EFI_SUCCESS - This driver supports this device.
189 EFI_UNSUPPORTED - This driver does not support this device.
190 EFI_DEVICE_ERROR - This driver cannot be started due to device
191 Error
192 EFI_OUT_OF_RESOURCES- Can't allocate memory resources
193 EFI_ALREADY_STARTED - Thios driver has been started
194 --*/
195 {
196 EFI_STATUS Status;
197 EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;
198 USB_FLOPPY_DEV *UsbFloppyDevice;
199
200 UsbFloppyDevice = NULL;
201 //
202 // Check whether Usb Atapi Protocol attached on the controller handle.
203 //
204 Status = gBS->OpenProtocol (
205 Controller,
206 &gEfiUsbAtapiProtocolGuid,
207 (VOID **) &AtapiProtocol,
208 This->DriverBindingHandle,
209 Controller,
210 EFI_OPEN_PROTOCOL_BY_DRIVER
211 );
212 if (EFI_ERROR (Status)) {
213 return Status;
214 }
215
216 Status = gBS->AllocatePool (
217 EfiBootServicesData,
218 sizeof (USB_FLOPPY_DEV),
219 (VOID **) &UsbFloppyDevice
220 );
221 if (EFI_ERROR (Status)) {
222 gBS->CloseProtocol (
223 Controller,
224 &gEfiUsbAtapiProtocolGuid,
225 This->DriverBindingHandle,
226 Controller
227 );
228 return Status;
229 }
230
231 ZeroMem (UsbFloppyDevice, sizeof (USB_FLOPPY_DEV));
232
233 UsbFloppyDevice->Handle = Controller;
234 UsbFloppyDevice->BlkIo.Media = &UsbFloppyDevice->BlkMedia;
235 UsbFloppyDevice->Signature = USB_FLOPPY_DEV_SIGNATURE;
236 UsbFloppyDevice->BlkIo.Reset = USBFloppyReset;
237 UsbFloppyDevice->BlkIo.ReadBlocks = USBFloppyReadBlocks;
238 UsbFloppyDevice->BlkIo.WriteBlocks = USBFloppyWriteBlocks;
239 UsbFloppyDevice->BlkIo.FlushBlocks = USBFloppyFlushBlocks;
240 UsbFloppyDevice->AtapiProtocol = AtapiProtocol;
241
242 //
243 // Identify drive type and retrieve media information.
244 //
245 Status = USBFloppyIdentify (UsbFloppyDevice);
246 if (EFI_ERROR (Status)) {
247 if (UsbFloppyDevice->SenseData != NULL) {
248 gBS->FreePool (UsbFloppyDevice->SenseData);
249 }
250
251 gBS->FreePool (UsbFloppyDevice);
252 gBS->CloseProtocol (
253 Controller,
254 &gEfiUsbAtapiProtocolGuid,
255 This->DriverBindingHandle,
256 Controller
257 );
258 return Status;
259 }
260 //
261 // Install Block I/O protocol for the usb floppy device.
262 //
263 Status = gBS->InstallProtocolInterface (
264 &Controller,
265 &gEfiBlockIoProtocolGuid,
266 EFI_NATIVE_INTERFACE,
267 &UsbFloppyDevice->BlkIo
268 );
269 if (EFI_ERROR (Status)) {
270 if (UsbFloppyDevice->SenseData != NULL) {
271 gBS->FreePool (UsbFloppyDevice->SenseData);
272 }
273
274 gBS->FreePool (UsbFloppyDevice);
275 gBS->CloseProtocol (
276 Controller,
277 &gEfiUsbAtapiProtocolGuid,
278 This->DriverBindingHandle,
279 Controller
280 );
281 return Status;
282 }
283
284 return EFI_SUCCESS;
285
286 }
287
288
289 EFI_STATUS
290 EFIAPI
291 USBFloppyDriverBindingStop (
292 IN EFI_DRIVER_BINDING_PROTOCOL *This,
293 IN EFI_HANDLE Controller,
294 IN UINTN NumberOfChildren,
295 IN EFI_HANDLE *ChildHandleBuffer
296 )
297 /*++
298
299 Routine Description:
300 Stop this driver on ControllerHandle. Support stoping any child handles
301 created by this driver.
302
303 Arguments:
304 This - Protocol instance pointer.
305 Controller - Handle of device to stop driver on
306 NumberOfChildren - Number of Children in the ChildHandleBuffer
307 ChildHandleBuffer - List of handles for the children we need to stop.
308
309 Returns:
310 EFI_SUCCESS
311 EFI_DEVICE_ERROR
312 others
313
314 --*/
315 {
316 EFI_STATUS Status;
317 USB_FLOPPY_DEV *UsbFloppyDevice;
318 EFI_BLOCK_IO_PROTOCOL *BlkIo;
319
320 //
321 // First find USB_FLOPPY_DEV
322 //
323 gBS->OpenProtocol (
324 Controller,
325 &gEfiBlockIoProtocolGuid,
326 (VOID **) &BlkIo,
327 This->DriverBindingHandle,
328 Controller,
329 EFI_OPEN_PROTOCOL_GET_PROTOCOL
330 );
331
332 UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (BlkIo);
333
334 //
335 // Uninstall Block I/O protocol from the device handle
336 //
337 Status = gBS->UninstallProtocolInterface (
338 Controller,
339 &gEfiBlockIoProtocolGuid,
340 &UsbFloppyDevice->BlkIo
341 );
342 if (EFI_ERROR (Status)) {
343 return Status;
344 }
345 //
346 // Stop using EFI_USB_ATAPI_PROTOCOL
347 //
348 gBS->CloseProtocol (
349 Controller,
350 &gEfiUsbAtapiProtocolGuid,
351 This->DriverBindingHandle,
352 Controller
353 );
354
355 if (UsbFloppyDevice->SenseData != NULL) {
356 gBS->FreePool (UsbFloppyDevice->SenseData);
357 }
358
359 gBS->FreePool (UsbFloppyDevice);
360
361 return EFI_SUCCESS;
362 }
363
364
365 STATIC
366 EFI_STATUS
367 EFIAPI
368 USBFloppyReset (
369 IN EFI_BLOCK_IO_PROTOCOL *This,
370 IN BOOLEAN ExtendedVerification
371 )
372 /*++
373
374 Routine Description:
375 Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
376
377 Arguments:
378 This The EFI_BLOCK_IO_PROTOCOL instance.
379 ExtendedVerification
380 Indicates that the driver may perform a more exhaustive
381 verification operation of the device during reset.
382 (This parameter is ingored in this driver.)
383
384 Returns:
385 EFI_SUCCESS - Success
386 --*/
387 {
388 USB_FLOPPY_DEV *UsbFloppyDevice;
389 EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
390 EFI_STATUS Status;
391
392 UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);
393
394 UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
395
396 //
397 // directly calling EFI_USB_ATAPI_PROTOCOL.Reset() to implement reset.
398 //
399 Status = UsbAtapiInterface->UsbAtapiReset (UsbAtapiInterface, ExtendedVerification);
400
401 return Status;
402 }
403
404 STATIC
405 EFI_STATUS
406 EFIAPI
407 USBFloppyReadBlocks (
408 IN EFI_BLOCK_IO_PROTOCOL *This,
409 IN UINT32 MediaId,
410 IN EFI_LBA LBA,
411 IN UINTN BufferSize,
412 OUT VOID *Buffer
413 )
414 /*++
415
416 Routine Description:
417 Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
418
419 Arguments:
420 This The EFI_BLOCK_IO_PROTOCOL instance.
421 MediaId The media id that the read request is for.
422 LBA The starting logical block address to read from on the device.
423 BufferSize
424 The size of the Buffer in bytes. This must be a multiple of
425 the intrinsic block size of the device.
426 Buffer A pointer to the destination buffer for the data. The caller
427 is responsible for either having implicit or explicit ownership
428 of the buffer.
429
430 Returns:
431 EFI_INVALID_PARAMETER - Parameter is error
432 EFI_SUCCESS - Success
433 EFI_DEVICE_ERROR - Hardware Error
434 EFI_NO_MEDIA - No media
435 EFI_MEDIA_CHANGED - Media Change
436 EFI_BAD_BUFFER_SIZE - Buffer size is bad
437 --*/
438 {
439 USB_FLOPPY_DEV *UsbFloppyDevice;
440 EFI_STATUS Status;
441 EFI_BLOCK_IO_MEDIA *Media;
442 UINTN BlockSize;
443 UINTN NumberOfBlocks;
444 BOOLEAN MediaChange;
445
446 Status = EFI_SUCCESS;
447 MediaChange = FALSE;
448 UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);
449
450 //
451 // Check parameters
452 //
453 if (!Buffer) {
454 Status = EFI_INVALID_PARAMETER;
455 goto Done;
456 }
457
458 if (BufferSize == 0) {
459 Status = EFI_SUCCESS;
460 goto Done;
461 }
462
463 UsbFloppyTestUnitReady (UsbFloppyDevice);
464
465 Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);
466 if (EFI_ERROR (Status)) {
467
468 Status = EFI_DEVICE_ERROR;
469 goto Done;
470 }
471
472 if (MediaChange) {
473 gBS->ReinstallProtocolInterface (
474 UsbFloppyDevice->Handle,
475 &gEfiBlockIoProtocolGuid,
476 &UsbFloppyDevice->BlkIo,
477 &UsbFloppyDevice->BlkIo
478 );
479 }
480
481 Media = UsbFloppyDevice->BlkIo.Media;
482 BlockSize = Media->BlockSize;
483 NumberOfBlocks = BufferSize / BlockSize;
484
485 if (!(Media->MediaPresent)) {
486 Status = EFI_NO_MEDIA;
487 goto Done;
488 }
489
490 if (MediaId != Media->MediaId) {
491 Status = EFI_MEDIA_CHANGED;
492 goto Done;
493 }
494
495 if (BufferSize % BlockSize != 0) {
496 Status = EFI_BAD_BUFFER_SIZE;
497 goto Done;
498 }
499
500 if (LBA > Media->LastBlock) {
501 Status = EFI_INVALID_PARAMETER;
502 goto Done;
503 }
504
505 if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
506 Status = EFI_INVALID_PARAMETER;
507 goto Done;
508 }
509
510 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
511 Status = EFI_INVALID_PARAMETER;
512 goto Done;
513 }
514
515 while (NumberOfBlocks > 0) {
516
517 if (NumberOfBlocks > BLOCK_UNIT) {
518 Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, BLOCK_UNIT);
519 } else {
520 Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks);
521 }
522
523 if (EFI_ERROR (Status)) {
524 This->Reset (This, TRUE);
525 Status = EFI_DEVICE_ERROR;
526 }
527
528 if (NumberOfBlocks > BLOCK_UNIT) {
529 NumberOfBlocks -= BLOCK_UNIT;
530 LBA += BLOCK_UNIT;
531 Buffer = (UINT8 *) Buffer + This->Media->BlockSize * BLOCK_UNIT;
532 } else {
533 NumberOfBlocks -= NumberOfBlocks;
534 LBA += NumberOfBlocks;
535 Buffer = (UINT8 *) Buffer + This->Media->BlockSize * NumberOfBlocks;
536 }
537 }
538
539 Done:
540 return Status;
541 }
542
543 STATIC
544 EFI_STATUS
545 EFIAPI
546 USBFloppyWriteBlocks (
547 IN EFI_BLOCK_IO_PROTOCOL *This,
548 IN UINT32 MediaId,
549 IN EFI_LBA LBA,
550 IN UINTN BufferSize,
551 IN VOID *Buffer
552 )
553 /*++
554
555 Routine Description:
556 Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
557
558 Arguments:
559 This The EFI_BLOCK_IO_PROTOCOL instance.
560 MediaId The media id that the write request is for.
561 LBA The starting logical block address to be written.
562 The caller is responsible for writing to only
563 legitimate locations.
564 BufferSize
565 The size of the Buffer in bytes. This must be a multiple of
566 the intrinsic block size of the device.
567 Buffer A pointer to the source buffer for the data. The caller
568 is responsible for either having implicit or explicit ownership
569 of the buffer.
570
571 Returns:
572 EFI_INVALID_PARAMETER - Parameter is error
573 EFI_SUCCESS - Success
574 EFI_DEVICE_ERROR - Hardware Error
575 EFI_NO_MEDIA - No media
576 EFI_MEDIA_CHANGED - Media Change
577 EFI_BAD_BUFFER_SIZE - Buffer size is bad
578
579 --*/
580 {
581 USB_FLOPPY_DEV *UsbFloppyDevice;
582 EFI_STATUS Status;
583 EFI_BLOCK_IO_MEDIA *Media;
584 UINTN BlockSize;
585 UINTN NumberOfBlocks;
586 BOOLEAN MediaChange;
587
588 Status = EFI_SUCCESS;
589 MediaChange = FALSE;
590
591 UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);
592
593 //
594 // Check parameters
595 //
596 if (!Buffer) {
597 Status = EFI_INVALID_PARAMETER;
598 goto Done;
599 }
600
601 if (BufferSize == 0) {
602 Status = EFI_SUCCESS;
603 goto Done;
604 }
605
606 UsbFloppyTestUnitReady (UsbFloppyDevice);
607
608 Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);
609 if (EFI_ERROR (Status)) {
610
611 Status = EFI_DEVICE_ERROR;
612 goto Done;
613 }
614
615 if (MediaChange) {
616 gBS->ReinstallProtocolInterface (
617 UsbFloppyDevice->Handle,
618 &gEfiBlockIoProtocolGuid,
619 &UsbFloppyDevice->BlkIo,
620 &UsbFloppyDevice->BlkIo
621 );
622 }
623
624 Media = UsbFloppyDevice->BlkIo.Media;
625 BlockSize = Media->BlockSize;
626 NumberOfBlocks = BufferSize / BlockSize;
627
628 if (!(Media->MediaPresent)) {
629 Status = EFI_NO_MEDIA;
630 goto Done;
631 }
632
633 if (MediaId != Media->MediaId) {
634 Status = EFI_MEDIA_CHANGED;
635 goto Done;
636 }
637
638 if (BufferSize % BlockSize != 0) {
639 Status = EFI_BAD_BUFFER_SIZE;
640 goto Done;
641 }
642
643 if (LBA > Media->LastBlock) {
644 Status = EFI_INVALID_PARAMETER;
645 goto Done;
646 }
647
648 if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
649 Status = EFI_INVALID_PARAMETER;
650 goto Done;
651 }
652
653 if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
654 Status = EFI_INVALID_PARAMETER;
655 goto Done;
656 }
657
658 if (UsbFloppyDevice->BlkMedia.ReadOnly) {
659 Status = EFI_WRITE_PROTECTED;
660 goto Done;
661 }
662
663 while (NumberOfBlocks > 0) {
664
665 if (NumberOfBlocks > BLOCK_UNIT) {
666 Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, BLOCK_UNIT);
667 } else {
668 Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks);
669 }
670
671 if (EFI_ERROR (Status)) {
672 This->Reset (This, TRUE);
673 Status = EFI_DEVICE_ERROR;
674 }
675
676 if (NumberOfBlocks > BLOCK_UNIT) {
677 NumberOfBlocks -= BLOCK_UNIT;
678 LBA += BLOCK_UNIT;
679 Buffer = (UINT8 *) Buffer + This->Media->BlockSize * BLOCK_UNIT;
680 } else {
681 NumberOfBlocks -= NumberOfBlocks;
682 LBA += NumberOfBlocks;
683 Buffer = (UINT8 *) Buffer + This->Media->BlockSize * NumberOfBlocks;
684 }
685 }
686
687 Done:
688
689 return Status;
690 }
691
692 STATIC
693 EFI_STATUS
694 EFIAPI
695 USBFloppyFlushBlocks (
696 IN EFI_BLOCK_IO_PROTOCOL *This
697 )
698 /*++
699
700 Routine Description:
701 Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
702 (In this driver, this function just returns EFI_SUCCESS.)
703
704 Arguments:
705 This The EFI_BLOCK_IO_PROTOCOL instance.
706
707 Returns:
708 EFI_SUCCESS - Success
709 --*/
710 {
711 return EFI_SUCCESS;
712 }