Remove Debug message and early test code in DiskIo
[mirror_edk2.git] / EdkModulePkg / Universal / Disk / DiskIo / Dxe / diskio.c
CommitLineData
b83a1237
LG
1/*++
2
3Copyright (c) 2006, Intel Corporation
4All rights reserved. This program and the accompanying materials
5are licensed and made available under the terms and conditions of the BSD License
6which accompanies this distribution. The full text of the license may be found at
7http://opensource.org/licenses/bsd-license.php
8
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12Module Name:
13
14 DiskIo.c
15
16Abstract:
17
18 DiskIo driver that layers it's self on every Block IO protocol in the system.
19 DiskIo converts a block oriented device to a byte oriented device.
20
21 ReadDisk may have to do reads that are not aligned on sector boundaries.
22 There are three cases:
23
24 UnderRun - The first byte is not on a sector boundary or the read request is
25 less than a sector in length.
26
27 Aligned - A read of N contiguous sectors.
28
29 OverRun - The last byte is not on a sector boundary.
30
31--*/
32
33#include "DiskIo.h"
34
35//
36// Prototypes
37// Driver model protocol interface
38//
39EFI_STATUS
40EFIAPI
41DiskIoDriverBindingSupported (
42 IN EFI_DRIVER_BINDING_PROTOCOL *This,
43 IN EFI_HANDLE ControllerHandle,
44 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
45 );
46
47EFI_STATUS
48EFIAPI
49DiskIoDriverBindingStart (
50 IN EFI_DRIVER_BINDING_PROTOCOL *This,
51 IN EFI_HANDLE ControllerHandle,
52 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
53 );
54
55EFI_STATUS
56EFIAPI
57DiskIoDriverBindingStop (
58 IN EFI_DRIVER_BINDING_PROTOCOL *This,
59 IN EFI_HANDLE ControllerHandle,
60 IN UINTN NumberOfChildren,
61 IN EFI_HANDLE *ChildHandleBuffer
62 );
63
64//
65// Disk I/O Protocol Interface
66//
67EFI_STATUS
68EFIAPI
69DiskIoReadDisk (
70 IN EFI_DISK_IO_PROTOCOL *This,
71 IN UINT32 MediaId,
72 IN UINT64 Offset,
73 IN UINTN BufferSize,
74 OUT VOID *Buffer
75 );
76
77EFI_STATUS
78EFIAPI
79DiskIoWriteDisk (
80 IN EFI_DISK_IO_PROTOCOL *This,
81 IN UINT32 MediaId,
82 IN UINT64 Offset,
83 IN UINTN BufferSize,
84 IN VOID *Buffer
85 );
86
87EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding = {
88 DiskIoDriverBindingSupported,
89 DiskIoDriverBindingStart,
90 DiskIoDriverBindingStop,
91 0x10,
92 NULL,
93 NULL
94};
95
96DISK_IO_PRIVATE_DATA gDiskIoPrivateDataTemplate = {
97 DISK_IO_PRIVATE_DATA_SIGNATURE,
98 {
99 EFI_DISK_IO_PROTOCOL_REVISION,
100 DiskIoReadDisk,
101 DiskIoWriteDisk
102 },
103 NULL
104};
105
106EFI_STATUS
107EFIAPI
108DiskIoDriverBindingSupported (
109 IN EFI_DRIVER_BINDING_PROTOCOL *This,
110 IN EFI_HANDLE ControllerHandle,
111 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
112 )
113/*++
114
115 Routine Description:
116 Test to see if this driver supports ControllerHandle. Any ControllerHandle
117 than contains a BlockIo protocol can be supported.
118
119 Arguments:
120 This - Protocol instance pointer.
121 ControllerHandle - Handle of device to test.
122 RemainingDevicePath - Not used.
123
124 Returns:
125 EFI_SUCCESS - This driver supports this device.
126 EFI_ALREADY_STARTED - This driver is already running on this device.
127 other - This driver does not support this device.
128
129--*/
130{
131 EFI_STATUS Status;
132 EFI_BLOCK_IO_PROTOCOL *BlockIo;
133
134 //
135 // Open the IO Abstraction(s) needed to perform the supported test.
136 //
137 Status = gBS->OpenProtocol (
138 ControllerHandle,
139 &gEfiBlockIoProtocolGuid,
140 (VOID **) &BlockIo,
141 This->DriverBindingHandle,
142 ControllerHandle,
143 EFI_OPEN_PROTOCOL_BY_DRIVER
144 );
145 if (EFI_ERROR (Status)) {
146 return Status;
147 }
148 //
149 // Close the I/O Abstraction(s) used to perform the supported test.
150 //
151 gBS->CloseProtocol (
152 ControllerHandle,
153 &gEfiBlockIoProtocolGuid,
154 This->DriverBindingHandle,
155 ControllerHandle
156 );
157 return EFI_SUCCESS;
158}
159
160EFI_STATUS
161EFIAPI
162DiskIoDriverBindingStart (
163 IN EFI_DRIVER_BINDING_PROTOCOL *This,
164 IN EFI_HANDLE ControllerHandle,
165 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
166 )
167/*++
168
169 Routine Description:
170 Start this driver on ControllerHandle by opening a Block IO protocol and
171 installing a Disk IO protocol on ControllerHandle.
172
173 Arguments:
174 This - Protocol instance pointer.
175 ControllerHandle - Handle of device to bind driver to.
176 RemainingDevicePath - Not used, always produce all possible children.
177
178 Returns:
179 EFI_SUCCESS - This driver is added to ControllerHandle.
180 EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
181 other - This driver does not support this device.
182
183--*/
184{
185 EFI_STATUS Status;
186 DISK_IO_PRIVATE_DATA *Private;
187
188 Private = NULL;
189
190 //
191 // Connect to the Block IO interface on ControllerHandle.
192 //
193 Status = gBS->OpenProtocol (
194 ControllerHandle,
195 &gEfiBlockIoProtocolGuid,
196 (VOID **) &gDiskIoPrivateDataTemplate.BlockIo,
197 This->DriverBindingHandle,
198 ControllerHandle,
199 EFI_OPEN_PROTOCOL_BY_DRIVER
200 );
201 if (EFI_ERROR (Status)) {
202 return Status;
203 }
204 //
205 // Initialize the Disk IO device instance.
206 //
207 Private = AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA), &gDiskIoPrivateDataTemplate);
208 if (Private == NULL) {
209 Status = EFI_OUT_OF_RESOURCES;
210 goto ErrorExit;
211 }
212 //
213 // Install protocol interfaces for the Disk IO device.
214 //
215 Status = gBS->InstallProtocolInterface (
216 &ControllerHandle,
217 &gEfiDiskIoProtocolGuid,
218 EFI_NATIVE_INTERFACE,
219 &Private->DiskIo
220 );
221
222ErrorExit:
223 if (EFI_ERROR (Status)) {
224
225 if (Private != NULL) {
226 gBS->FreePool (Private);
227 }
228
229 gBS->CloseProtocol (
230 ControllerHandle,
231 &gEfiBlockIoProtocolGuid,
232 This->DriverBindingHandle,
233 ControllerHandle
234 );
235 }
236
237 return Status;
238}
239
240EFI_STATUS
241EFIAPI
242DiskIoDriverBindingStop (
243 IN EFI_DRIVER_BINDING_PROTOCOL *This,
244 IN EFI_HANDLE ControllerHandle,
245 IN UINTN NumberOfChildren,
246 IN EFI_HANDLE *ChildHandleBuffer
247 )
248/*++
249
250 Routine Description:
251 Stop this driver on ControllerHandle by removing Disk IO protocol and closing
252 the Block IO protocol on ControllerHandle.
253
254 Arguments:
255 This - Protocol instance pointer.
256 ControllerHandle - Handle of device to stop driver on.
257 NumberOfChildren - Not used.
258 ChildHandleBuffer - Not used.
259
260 Returns:
261 EFI_SUCCESS - This driver is removed ControllerHandle.
262 other - This driver was not removed from this device.
263 EFI_UNSUPPORTED
264
265--*/
266{
267 EFI_STATUS Status;
268 EFI_DISK_IO_PROTOCOL *DiskIo;
269 DISK_IO_PRIVATE_DATA *Private;
270
271 //
272 // Get our context back.
273 //
274 Status = gBS->OpenProtocol (
275 ControllerHandle,
276 &gEfiDiskIoProtocolGuid,
277 (VOID **) &DiskIo,
278 This->DriverBindingHandle,
279 ControllerHandle,
280 EFI_OPEN_PROTOCOL_GET_PROTOCOL
281 );
282 if (EFI_ERROR (Status)) {
283 return EFI_UNSUPPORTED;
284 }
285
286 Private = DISK_IO_PRIVATE_DATA_FROM_THIS (DiskIo);
287
288 Status = gBS->UninstallProtocolInterface (
289 ControllerHandle,
290 &gEfiDiskIoProtocolGuid,
291 &Private->DiskIo
292 );
293 if (!EFI_ERROR (Status)) {
294
295 Status = gBS->CloseProtocol (
296 ControllerHandle,
297 &gEfiBlockIoProtocolGuid,
298 This->DriverBindingHandle,
299 ControllerHandle
300 );
301 }
302
303 if (!EFI_ERROR (Status)) {
304 gBS->FreePool (Private);
305 }
306
307 return Status;
308}
309
310EFI_STATUS
311EFIAPI
312DiskIoReadDisk (
313 IN EFI_DISK_IO_PROTOCOL *This,
314 IN UINT32 MediaId,
315 IN UINT64 Offset,
316 IN UINTN BufferSize,
317 OUT VOID *Buffer
318 )
319/*++
320
321 Routine Description:
322 Read BufferSize bytes from Offset into Buffer.
323
324 Reads may support reads that are not aligned on
325 sector boundaries. There are three cases:
326
327 UnderRun - The first byte is not on a sector boundary or the read request is
328 less than a sector in length.
329
330 Aligned - A read of N contiguous sectors.
331
332 OverRun - The last byte is not on a sector boundary.
333
334
335 Arguments:
336 This - Protocol instance pointer.
337 MediaId - Id of the media, changes every time the media is replaced.
338 Offset - The starting byte offset to read from.
339 BufferSize - Size of Buffer.
340 Buffer - Buffer containing read data.
341
342 Returns:
343 EFI_SUCCESS - The data was read correctly from the device.
344 EFI_DEVICE_ERROR - The device reported an error while performing the read.
345 EFI_NO_MEDIA - There is no media in the device.
346 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
347 EFI_INVALID_PARAMETER - The read request contains device addresses that are not
348 valid for the device.
349 EFI_OUT_OF_RESOURCES
350
351--*/
352{
353 EFI_STATUS Status;
354 DISK_IO_PRIVATE_DATA *Private;
355 EFI_BLOCK_IO_PROTOCOL *BlockIo;
356 EFI_BLOCK_IO_MEDIA *Media;
357 UINT32 BlockSize;
358 UINT64 Lba;
359 UINT64 OverRunLba;
360 UINT32 UnderRun;
361 UINT32 OverRun;
362 BOOLEAN TransactionComplete;
363 UINTN WorkingBufferSize;
364 UINT8 *WorkingBuffer;
365 UINTN Length;
366 UINT8 *Data;
367 UINT8 *PreData;
368 UINTN IsBufferAligned;
369 UINTN DataBufferSize;
370 BOOLEAN LastRead;
371
372 Private = DISK_IO_PRIVATE_DATA_FROM_THIS (This);
373
374 BlockIo = Private->BlockIo;
375 Media = BlockIo->Media;
376 BlockSize = Media->BlockSize;
377
378 if (Media->MediaId != MediaId) {
379 return EFI_MEDIA_CHANGED;
380 }
381
382 WorkingBuffer = Buffer;
383 WorkingBufferSize = BufferSize;
384
385 //
386 // Allocate a temporary buffer for operation
387 //
388 DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM;
389
390 if (Media->IoAlign > 1) {
391 PreData = AllocatePool (DataBufferSize + Media->IoAlign);
392 Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign;
393 } else {
394 PreData = AllocatePool (DataBufferSize);
395 Data = PreData;
396 }
397
398 if (PreData == NULL) {
399 return EFI_OUT_OF_RESOURCES;
400 }
401
402 Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun);
403
404 Length = BlockSize - UnderRun;
405 TransactionComplete = FALSE;
406
407 Status = EFI_SUCCESS;
408 if (UnderRun != 0) {
409 //
410 // Offset starts in the middle of an Lba, so read the entire block.
411 //
412 Status = BlockIo->ReadBlocks (
413 BlockIo,
414 MediaId,
415 Lba,
416 BlockSize,
417 Data
418 );
419
420 if (EFI_ERROR (Status)) {
421 goto Done;
422 }
423
424 if (Length > BufferSize) {
425 Length = BufferSize;
426 TransactionComplete = TRUE;
427 }
428
429 CopyMem (WorkingBuffer, Data + UnderRun, Length);
430
431 WorkingBuffer += Length;
432
433 WorkingBufferSize -= Length;
434 if (WorkingBufferSize == 0) {
435 goto Done;
436 }
437
438 Lba += 1;
439 }
440
441 OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun);
442
443 if (!TransactionComplete && WorkingBufferSize >= BlockSize) {
444 //
445 // If the DiskIo maps directly to a BlockIo device do the read.
446 //
447 if (OverRun != 0) {
448 WorkingBufferSize -= OverRun;
449 }
450 //
451 // Check buffer alignment
452 //
453 IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1);
454
455 if (Media->IoAlign <= 1 || IsBufferAligned == 0) {
456 //
457 // Alignment is satisfied, so read them together
458 //
459 Status = BlockIo->ReadBlocks (
460 BlockIo,
461 MediaId,
462 Lba,
463 WorkingBufferSize,
464 WorkingBuffer
465 );
466
467 if (EFI_ERROR (Status)) {
468 goto Done;
469 }
470
471 WorkingBuffer += WorkingBufferSize;
472
473 } else {
474 //
475 // Use the allocated buffer instead of the original buffer
476 // to avoid alignment issue.
477 // Here, the allocated buffer (8-byte align) can satisfy the alignment
478 //
479 LastRead = FALSE;
480 do {
481 if (WorkingBufferSize <= DataBufferSize) {
482 //
483 // It is the last calling to readblocks in this loop
484 //
485 DataBufferSize = WorkingBufferSize;
486 LastRead = TRUE;
487 }
488
489 Status = BlockIo->ReadBlocks (
490 BlockIo,
491 MediaId,
492 Lba,
493 DataBufferSize,
494 Data
495 );
496 if (EFI_ERROR (Status)) {
497 goto Done;
498 }
499
500 CopyMem (WorkingBuffer, Data, DataBufferSize);
501 WorkingBufferSize -= DataBufferSize;
502 WorkingBuffer += DataBufferSize;
503 Lba += DATA_BUFFER_BLOCK_NUM;
504 } while (!LastRead);
505 }
506 }
507
508 if (!TransactionComplete && OverRun != 0) {
509 //
510 // Last read is not a complete block.
511 //
512 Status = BlockIo->ReadBlocks (
513 BlockIo,
514 MediaId,
515 OverRunLba,
516 BlockSize,
517 Data
518 );
519
520 if (EFI_ERROR (Status)) {
521 goto Done;
522 }
523
524 CopyMem (WorkingBuffer, Data, OverRun);
525 }
526
527Done:
528 if (PreData != NULL) {
529 gBS->FreePool (PreData);
530 }
531
532 return Status;
533}
534
535EFI_STATUS
536EFIAPI
537DiskIoWriteDisk (
538 IN EFI_DISK_IO_PROTOCOL *This,
539 IN UINT32 MediaId,
540 IN UINT64 Offset,
541 IN UINTN BufferSize,
542 IN VOID *Buffer
543 )
544/*++
545
546 Routine Description:
547 Read BufferSize bytes from Offset into Buffer.
548
549 Writes may require a read modify write to support writes that are not
550 aligned on sector boundaries. There are three cases:
551
552 UnderRun - The first byte is not on a sector boundary or the write request
553 is less than a sector in length. Read modify write is required.
554
555 Aligned - A write of N contiguous sectors.
556
557 OverRun - The last byte is not on a sector boundary. Read modified write
558 required.
559
560 Arguments:
561 This - Protocol instance pointer.
562 MediaId - Id of the media, changes every time the media is replaced.
563 Offset - The starting byte offset to read from.
564 BufferSize - Size of Buffer.
565 Buffer - Buffer containing read data.
566
567 Returns:
568 EFI_SUCCESS - The data was written correctly to the device.
569 EFI_WRITE_PROTECTED - The device can not be written to.
570 EFI_DEVICE_ERROR - The device reported an error while performing the write.
571 EFI_NO_MEDIA - There is no media in the device.
572 EFI_MEDIA_CHNAGED - The MediaId does not matched the current device.
573 EFI_INVALID_PARAMETER - The write request contains device addresses that are not
574 valid for the device.
575 EFI_OUT_OF_RESOURCES
576
577--*/
578{
579 EFI_STATUS Status;
580 DISK_IO_PRIVATE_DATA *Private;
581 EFI_BLOCK_IO_PROTOCOL *BlockIo;
582 EFI_BLOCK_IO_MEDIA *Media;
583 UINT32 BlockSize;
584 UINT64 Lba;
585 UINT64 OverRunLba;
586 UINT32 UnderRun;
587 UINT32 OverRun;
588 BOOLEAN TransactionComplete;
589 UINTN WorkingBufferSize;
590 UINT8 *WorkingBuffer;
591 UINTN Length;
592 UINT8 *Data;
593 UINT8 *PreData;
594 UINTN IsBufferAligned;
595 UINTN DataBufferSize;
596 BOOLEAN LastWrite;
597
598 Private = DISK_IO_PRIVATE_DATA_FROM_THIS (This);
599
600 BlockIo = Private->BlockIo;
601 Media = BlockIo->Media;
602 BlockSize = Media->BlockSize;
603
604 if (Media->ReadOnly) {
605 return EFI_WRITE_PROTECTED;
606 }
607
608 if (Media->MediaId != MediaId) {
609 return EFI_MEDIA_CHANGED;
610 }
611
612 DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM;
613
614 if (Media->IoAlign > 1) {
615 PreData = AllocatePool (DataBufferSize + Media->IoAlign);
616 Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign;
617 } else {
618 PreData = AllocatePool (DataBufferSize);
619 Data = PreData;
620 }
621
622 if (PreData == NULL) {
623 return EFI_OUT_OF_RESOURCES;
624 }
625
626 WorkingBuffer = Buffer;
627 WorkingBufferSize = BufferSize;
628
629 Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun);
630
631 Length = BlockSize - UnderRun;
632 TransactionComplete = FALSE;
633
634 Status = EFI_SUCCESS;
635 if (UnderRun != 0) {
636 //
637 // Offset starts in the middle of an Lba, so do read modify write.
638 //
639 Status = BlockIo->ReadBlocks (
640 BlockIo,
641 MediaId,
642 Lba,
643 BlockSize,
644 Data
645 );
646
647 if (EFI_ERROR (Status)) {
648 goto Done;
649 }
650
651 if (Length > BufferSize) {
652 Length = BufferSize;
653 TransactionComplete = TRUE;
654 }
655
656 CopyMem (Data + UnderRun, WorkingBuffer, Length);
657
658 Status = BlockIo->WriteBlocks (
659 BlockIo,
660 MediaId,
661 Lba,
662 BlockSize,
663 Data
664 );
665 if (EFI_ERROR (Status)) {
666 goto Done;
667 }
668
669 WorkingBuffer += Length;
670 WorkingBufferSize -= Length;
671 if (WorkingBufferSize == 0) {
672 goto Done;
673 }
674
675 Lba += 1;
676 }
677
678 OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun);
679
680 if (!TransactionComplete && WorkingBufferSize >= BlockSize) {
681 //
682 // If the DiskIo maps directly to a BlockIo device do the write.
683 //
684 if (OverRun != 0) {
685 WorkingBufferSize -= OverRun;
686 }
687 //
688 // Check buffer alignment
689 //
690 IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1);
691
692 if (Media->IoAlign <= 1 || IsBufferAligned == 0) {
693 //
694 // Alignment is satisfied, so write them together
695 //
696 Status = BlockIo->WriteBlocks (
697 BlockIo,
698 MediaId,
699 Lba,
700 WorkingBufferSize,
701 WorkingBuffer
702 );
703
704 if (EFI_ERROR (Status)) {
705 goto Done;
706 }
707
708 WorkingBuffer += WorkingBufferSize;
709
710 } else {
711 //
712 // The buffer parameter is not aligned with the request
713 // So use the allocated instead.
714 // It can fit almost all the cases.
715 //
716 LastWrite = FALSE;
717 do {
718 if (WorkingBufferSize <= DataBufferSize) {
719 //
720 // It is the last calling to writeblocks in this loop
721 //
722 DataBufferSize = WorkingBufferSize;
723 LastWrite = TRUE;
724 }
725
726 CopyMem (Data, WorkingBuffer, DataBufferSize);
727 Status = BlockIo->WriteBlocks (
728 BlockIo,
729 MediaId,
730 Lba,
731 DataBufferSize,
732 Data
733 );
734 if (EFI_ERROR (Status)) {
735 goto Done;
736 }
737
738 WorkingBufferSize -= DataBufferSize;
739 WorkingBuffer += DataBufferSize;
740 Lba += DATA_BUFFER_BLOCK_NUM;
741 } while (!LastWrite);
742 }
743 }
744
745 if (!TransactionComplete && OverRun != 0) {
746 //
747 // Last bit is not a complete block, so do a read modify write.
748 //
749 Status = BlockIo->ReadBlocks (
750 BlockIo,
751 MediaId,
752 OverRunLba,
753 BlockSize,
754 Data
755 );
756
757 if (EFI_ERROR (Status)) {
758 goto Done;
759 }
760
761 CopyMem (Data, WorkingBuffer, OverRun);
762
763 Status = BlockIo->WriteBlocks (
764 BlockIo,
765 MediaId,
766 OverRunLba,
767 BlockSize,
768 Data
769 );
770 if (EFI_ERROR (Status)) {
771 goto Done;
772 }
773 }
774
775Done:
776 if (PreData != NULL) {
777 gBS->FreePool (PreData);
778 }
779
780 return Status;
781}