2 Produce EFI_BLOCK_IO_PROTOCOL on a RAM disk device.
4 Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "RamDiskImpl.h"
18 // The EFI_BLOCK_IO_PROTOCOL instances that is installed onto the handle
19 // for newly registered RAM disks
21 EFI_BLOCK_IO_PROTOCOL mRamDiskBlockIoTemplate
= {
22 EFI_BLOCK_IO_PROTOCOL_REVISION
,
23 (EFI_BLOCK_IO_MEDIA
*) 0,
25 RamDiskBlkIoReadBlocks
,
26 RamDiskBlkIoWriteBlocks
,
27 RamDiskBlkIoFlushBlocks
31 // The EFI_BLOCK_IO_PROTOCOL2 instances that is installed onto the handle
32 // for newly registered RAM disks
34 EFI_BLOCK_IO2_PROTOCOL mRamDiskBlockIo2Template
= {
35 (EFI_BLOCK_IO_MEDIA
*) 0,
37 RamDiskBlkIo2ReadBlocksEx
,
38 RamDiskBlkIo2WriteBlocksEx
,
39 RamDiskBlkIo2FlushBlocksEx
44 Initialize the BlockIO & BlockIO2 protocol of a RAM disk device.
46 @param[in] PrivateData Points to RAM disk private data.
51 IN RAM_DISK_PRIVATE_DATA
*PrivateData
54 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
55 EFI_BLOCK_IO2_PROTOCOL
*BlockIo2
;
56 EFI_BLOCK_IO_MEDIA
*Media
;
59 BlockIo
= &PrivateData
->BlockIo
;
60 BlockIo2
= &PrivateData
->BlockIo2
;
61 Media
= &PrivateData
->Media
;
63 CopyMem (BlockIo
, &mRamDiskBlockIoTemplate
, sizeof (EFI_BLOCK_IO_PROTOCOL
));
64 CopyMem (BlockIo2
, &mRamDiskBlockIo2Template
, sizeof (EFI_BLOCK_IO2_PROTOCOL
));
66 BlockIo
->Media
= Media
;
67 BlockIo2
->Media
= Media
;
68 Media
->RemovableMedia
= FALSE
;
69 Media
->MediaPresent
= TRUE
;
70 Media
->LogicalPartition
= FALSE
;
71 Media
->ReadOnly
= FALSE
;
72 Media
->WriteCaching
= FALSE
;
74 for (Media
->BlockSize
= RAM_DISK_DEFAULT_BLOCK_SIZE
;
75 Media
->BlockSize
>= 1;
76 Media
->BlockSize
= Media
->BlockSize
>> 1) {
77 Media
->LastBlock
= DivU64x32Remainder (PrivateData
->Size
, Media
->BlockSize
, &Remainder
) - 1;
82 ASSERT (Media
->BlockSize
!= 0);
89 Reset the Block Device.
91 @param This Indicates a pointer to the calling context.
92 @param ExtendedVerification Driver may perform diagnostics on reset.
94 @retval EFI_SUCCESS The device was reset.
95 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
102 IN EFI_BLOCK_IO_PROTOCOL
*This
,
103 IN BOOLEAN ExtendedVerification
111 Read BufferSize bytes from Lba into Buffer.
113 @param[in] This Indicates a pointer to the calling context.
114 @param[in] MediaId Id of the media, changes every time the media is
116 @param[in] Lba The starting Logical Block Address to read from.
117 @param[in] BufferSize Size of Buffer, must be a multiple of device block
119 @param[out] Buffer A pointer to the destination buffer for the data.
120 The caller is responsible for either having
121 implicit or explicit ownership of the buffer.
123 @retval EFI_SUCCESS The data was read correctly from the device.
124 @retval EFI_DEVICE_ERROR The device reported an error while performing
126 @retval EFI_NO_MEDIA There is no media in the device.
127 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current
129 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
131 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
132 valid, or the buffer is not on proper alignment.
137 RamDiskBlkIoReadBlocks (
138 IN EFI_BLOCK_IO_PROTOCOL
*This
,
145 RAM_DISK_PRIVATE_DATA
*PrivateData
;
146 UINTN NumberOfBlocks
;
148 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO (This
);
150 if (MediaId
!= PrivateData
->Media
.MediaId
) {
151 return EFI_MEDIA_CHANGED
;
154 if (Buffer
== NULL
) {
155 return EFI_INVALID_PARAMETER
;
158 if (BufferSize
== 0) {
162 if ((BufferSize
% PrivateData
->Media
.BlockSize
) != 0) {
163 return EFI_BAD_BUFFER_SIZE
;
166 if (Lba
> PrivateData
->Media
.LastBlock
) {
167 return EFI_INVALID_PARAMETER
;
170 NumberOfBlocks
= BufferSize
/ PrivateData
->Media
.BlockSize
;
171 if ((Lba
+ NumberOfBlocks
- 1) > PrivateData
->Media
.LastBlock
) {
172 return EFI_INVALID_PARAMETER
;
177 (VOID
*)(UINTN
)(PrivateData
->StartingAddr
+ MultU64x32 (Lba
, PrivateData
->Media
.BlockSize
)),
186 Write BufferSize bytes from Lba into Buffer.
188 @param[in] This Indicates a pointer to the calling context.
189 @param[in] MediaId The media ID that the write request is for.
190 @param[in] Lba The starting logical block address to be written.
191 The caller is responsible for writing to only
192 legitimate locations.
193 @param[in] BufferSize Size of Buffer, must be a multiple of device block
195 @param[in] Buffer A pointer to the source buffer for the data.
197 @retval EFI_SUCCESS The data was written correctly to the device.
198 @retval EFI_WRITE_PROTECTED The device can not be written to.
199 @retval EFI_DEVICE_ERROR The device reported an error while performing
201 @retval EFI_NO_MEDIA There is no media in the device.
202 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current
204 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
206 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
207 valid, or the buffer is not on proper alignment.
212 RamDiskBlkIoWriteBlocks (
213 IN EFI_BLOCK_IO_PROTOCOL
*This
,
220 RAM_DISK_PRIVATE_DATA
*PrivateData
;
221 UINTN NumberOfBlocks
;
223 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO (This
);
225 if (MediaId
!= PrivateData
->Media
.MediaId
) {
226 return EFI_MEDIA_CHANGED
;
229 if (TRUE
== PrivateData
->Media
.ReadOnly
) {
230 return EFI_WRITE_PROTECTED
;
233 if (Buffer
== NULL
) {
234 return EFI_INVALID_PARAMETER
;
237 if (BufferSize
== 0) {
241 if ((BufferSize
% PrivateData
->Media
.BlockSize
) != 0) {
242 return EFI_BAD_BUFFER_SIZE
;
245 if (Lba
> PrivateData
->Media
.LastBlock
) {
246 return EFI_INVALID_PARAMETER
;
249 NumberOfBlocks
= BufferSize
/ PrivateData
->Media
.BlockSize
;
250 if ((Lba
+ NumberOfBlocks
- 1) > PrivateData
->Media
.LastBlock
) {
251 return EFI_INVALID_PARAMETER
;
255 (VOID
*)(UINTN
)(PrivateData
->StartingAddr
+ MultU64x32 (Lba
, PrivateData
->Media
.BlockSize
)),
265 Flush the Block Device.
267 @param[in] This Indicates a pointer to the calling context.
269 @retval EFI_SUCCESS All outstanding data was written to the device.
270 @retval EFI_DEVICE_ERROR The device reported an error while writting
272 @retval EFI_NO_MEDIA There is no media in the device.
277 RamDiskBlkIoFlushBlocks (
278 IN EFI_BLOCK_IO_PROTOCOL
*This
286 Resets the block device hardware.
288 @param[in] This The pointer of EFI_BLOCK_IO2_PROTOCOL.
289 @param[in] ExtendedVerification The flag about if extend verificate.
291 @retval EFI_SUCCESS The device was reset.
292 @retval EFI_DEVICE_ERROR The block device is not functioning correctly
293 and could not be reset.
299 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
300 IN BOOLEAN ExtendedVerification
308 Reads the requested number of blocks from the device.
310 @param[in] This Indicates a pointer to the calling context.
311 @param[in] MediaId The media ID that the read request is for.
312 @param[in] Lba The starting logical block address to read
314 @param[in, out] Token A pointer to the token associated with the
316 @param[in] BufferSize The size of the Buffer in bytes. This must be
317 a multiple of the intrinsic block size of the
319 @param[out] Buffer A pointer to the destination buffer for the
320 data. The caller is responsible for either
321 having implicit or explicit ownership of the
324 @retval EFI_SUCCESS The read request was queued if Token->Event
325 is not NULL. The data was read correctly from
326 the device if the Token->Event is NULL.
327 @retval EFI_DEVICE_ERROR The device reported an error while attempting
328 to perform the read operation.
329 @retval EFI_NO_MEDIA There is no media in the device.
330 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
331 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
332 the intrinsic block size of the device.
333 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
334 valid, or the buffer is not on proper
336 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
342 RamDiskBlkIo2ReadBlocksEx (
343 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
346 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
351 RAM_DISK_PRIVATE_DATA
*PrivateData
;
354 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO2 (This
);
356 Status
= RamDiskBlkIoReadBlocks (
357 &PrivateData
->BlockIo
,
363 if (EFI_ERROR (Status
)) {
368 // If caller's event is given, signal it after the memory read completes.
370 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
371 Token
->TransactionStatus
= EFI_SUCCESS
;
372 gBS
->SignalEvent (Token
->Event
);
380 Writes a specified number of blocks to the device.
382 @param[in] This Indicates a pointer to the calling context.
383 @param[in] MediaId The media ID that the write request is for.
384 @param[in] Lba The starting logical block address to be
385 written. The caller is responsible for
386 writing to only legitimate locations.
387 @param[in, out] Token A pointer to the token associated with the
389 @param[in] BufferSize The size in bytes of Buffer. This must be a
390 multiple of the intrinsic block size of the
392 @param[in] Buffer A pointer to the source buffer for the data.
394 @retval EFI_SUCCESS The write request was queued if Event is not
395 NULL. The data was written correctly to the
396 device if the Event is NULL.
397 @retval EFI_WRITE_PROTECTED The device cannot be written to.
398 @retval EFI_NO_MEDIA There is no media in the device.
399 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
400 @retval EFI_DEVICE_ERROR The device reported an error while attempting
401 to perform the write operation.
402 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
403 the intrinsic block size of the device.
404 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
405 valid, or the buffer is not on proper
407 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
413 RamDiskBlkIo2WriteBlocksEx (
414 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
417 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
422 RAM_DISK_PRIVATE_DATA
*PrivateData
;
425 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO2 (This
);
427 Status
= RamDiskBlkIoWriteBlocks (
428 &PrivateData
->BlockIo
,
434 if (EFI_ERROR (Status
)) {
439 // If caller's event is given, signal it after the memory write completes.
441 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
442 Token
->TransactionStatus
= EFI_SUCCESS
;
443 gBS
->SignalEvent (Token
->Event
);
451 Flushes all modified data to a physical block device.
453 @param[in] This Indicates a pointer to the calling context.
454 @param[in, out] Token A pointer to the token associated with the
457 @retval EFI_SUCCESS The flush request was queued if Event is not
458 NULL. All outstanding data was written
459 correctly to the device if the Event is NULL.
460 @retval EFI_DEVICE_ERROR The device reported an error while attempting
462 @retval EFI_WRITE_PROTECTED The device cannot be written to.
463 @retval EFI_NO_MEDIA There is no media in the device.
464 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
465 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
471 RamDiskBlkIo2FlushBlocksEx (
472 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
473 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
476 RAM_DISK_PRIVATE_DATA
*PrivateData
;
478 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO2 (This
);
480 if (TRUE
== PrivateData
->Media
.ReadOnly
) {
481 return EFI_WRITE_PROTECTED
;
485 // If caller's event is given, signal it directly.
487 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
488 Token
->TransactionStatus
= EFI_SUCCESS
;
489 gBS
->SignalEvent (Token
->Event
);