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