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