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