2 Produce EFI_BLOCK_IO_PROTOCOL on a RAM disk device.
4 Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "RamDiskImpl.h"
12 // The EFI_BLOCK_IO_PROTOCOL instances that is installed onto the handle
13 // for newly registered RAM disks
15 EFI_BLOCK_IO_PROTOCOL mRamDiskBlockIoTemplate
= {
16 EFI_BLOCK_IO_PROTOCOL_REVISION
,
17 (EFI_BLOCK_IO_MEDIA
*) 0,
19 RamDiskBlkIoReadBlocks
,
20 RamDiskBlkIoWriteBlocks
,
21 RamDiskBlkIoFlushBlocks
25 // The EFI_BLOCK_IO_PROTOCOL2 instances that is installed onto the handle
26 // for newly registered RAM disks
28 EFI_BLOCK_IO2_PROTOCOL mRamDiskBlockIo2Template
= {
29 (EFI_BLOCK_IO_MEDIA
*) 0,
31 RamDiskBlkIo2ReadBlocksEx
,
32 RamDiskBlkIo2WriteBlocksEx
,
33 RamDiskBlkIo2FlushBlocksEx
38 Initialize the BlockIO & BlockIO2 protocol of a RAM disk device.
40 @param[in] PrivateData Points to RAM disk private data.
45 IN RAM_DISK_PRIVATE_DATA
*PrivateData
48 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
49 EFI_BLOCK_IO2_PROTOCOL
*BlockIo2
;
50 EFI_BLOCK_IO_MEDIA
*Media
;
53 BlockIo
= &PrivateData
->BlockIo
;
54 BlockIo2
= &PrivateData
->BlockIo2
;
55 Media
= &PrivateData
->Media
;
57 CopyMem (BlockIo
, &mRamDiskBlockIoTemplate
, sizeof (EFI_BLOCK_IO_PROTOCOL
));
58 CopyMem (BlockIo2
, &mRamDiskBlockIo2Template
, sizeof (EFI_BLOCK_IO2_PROTOCOL
));
60 BlockIo
->Media
= Media
;
61 BlockIo2
->Media
= Media
;
62 Media
->RemovableMedia
= FALSE
;
63 Media
->MediaPresent
= TRUE
;
64 Media
->LogicalPartition
= FALSE
;
65 Media
->ReadOnly
= FALSE
;
66 Media
->WriteCaching
= FALSE
;
68 for (Media
->BlockSize
= RAM_DISK_DEFAULT_BLOCK_SIZE
;
69 Media
->BlockSize
>= 1;
70 Media
->BlockSize
= Media
->BlockSize
>> 1) {
71 Media
->LastBlock
= DivU64x32Remainder (PrivateData
->Size
, Media
->BlockSize
, &Remainder
) - 1;
76 ASSERT (Media
->BlockSize
!= 0);
83 Reset the Block Device.
85 @param This Indicates a pointer to the calling context.
86 @param ExtendedVerification Driver may perform diagnostics on reset.
88 @retval EFI_SUCCESS The device was reset.
89 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
96 IN EFI_BLOCK_IO_PROTOCOL
*This
,
97 IN BOOLEAN ExtendedVerification
105 Read BufferSize bytes from Lba into Buffer.
107 @param[in] This Indicates a pointer to the calling context.
108 @param[in] MediaId Id of the media, changes every time the media is
110 @param[in] Lba The starting Logical Block Address to read from.
111 @param[in] BufferSize Size of Buffer, must be a multiple of device block
113 @param[out] Buffer A pointer to the destination buffer for the data.
114 The caller is responsible for either having
115 implicit or explicit ownership of the buffer.
117 @retval EFI_SUCCESS The data was read correctly from the device.
118 @retval EFI_DEVICE_ERROR The device reported an error while performing
120 @retval EFI_NO_MEDIA There is no media in the device.
121 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current
123 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
125 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
126 valid, or the buffer is not on proper alignment.
131 RamDiskBlkIoReadBlocks (
132 IN EFI_BLOCK_IO_PROTOCOL
*This
,
139 RAM_DISK_PRIVATE_DATA
*PrivateData
;
140 UINTN NumberOfBlocks
;
142 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO (This
);
144 if (MediaId
!= PrivateData
->Media
.MediaId
) {
145 return EFI_MEDIA_CHANGED
;
148 if (Buffer
== NULL
) {
149 return EFI_INVALID_PARAMETER
;
152 if (BufferSize
== 0) {
156 if ((BufferSize
% PrivateData
->Media
.BlockSize
) != 0) {
157 return EFI_BAD_BUFFER_SIZE
;
160 if (Lba
> PrivateData
->Media
.LastBlock
) {
161 return EFI_INVALID_PARAMETER
;
164 NumberOfBlocks
= BufferSize
/ PrivateData
->Media
.BlockSize
;
165 if ((Lba
+ NumberOfBlocks
- 1) > PrivateData
->Media
.LastBlock
) {
166 return EFI_INVALID_PARAMETER
;
171 (VOID
*)(UINTN
)(PrivateData
->StartingAddr
+ MultU64x32 (Lba
, PrivateData
->Media
.BlockSize
)),
180 Write BufferSize bytes from Lba into Buffer.
182 @param[in] This Indicates a pointer to the calling context.
183 @param[in] MediaId The media ID that the write request is for.
184 @param[in] Lba The starting logical block address to be written.
185 The caller is responsible for writing to only
186 legitimate locations.
187 @param[in] BufferSize Size of Buffer, must be a multiple of device block
189 @param[in] Buffer A pointer to the source buffer for the data.
191 @retval EFI_SUCCESS The data was written correctly to the device.
192 @retval EFI_WRITE_PROTECTED The device can not be written to.
193 @retval EFI_DEVICE_ERROR The device reported an error while performing
195 @retval EFI_NO_MEDIA There is no media in the device.
196 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current
198 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
200 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
201 valid, or the buffer is not on proper alignment.
206 RamDiskBlkIoWriteBlocks (
207 IN EFI_BLOCK_IO_PROTOCOL
*This
,
214 RAM_DISK_PRIVATE_DATA
*PrivateData
;
215 UINTN NumberOfBlocks
;
217 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO (This
);
219 if (MediaId
!= PrivateData
->Media
.MediaId
) {
220 return EFI_MEDIA_CHANGED
;
223 if (TRUE
== PrivateData
->Media
.ReadOnly
) {
224 return EFI_WRITE_PROTECTED
;
227 if (Buffer
== NULL
) {
228 return EFI_INVALID_PARAMETER
;
231 if (BufferSize
== 0) {
235 if ((BufferSize
% PrivateData
->Media
.BlockSize
) != 0) {
236 return EFI_BAD_BUFFER_SIZE
;
239 if (Lba
> PrivateData
->Media
.LastBlock
) {
240 return EFI_INVALID_PARAMETER
;
243 NumberOfBlocks
= BufferSize
/ PrivateData
->Media
.BlockSize
;
244 if ((Lba
+ NumberOfBlocks
- 1) > PrivateData
->Media
.LastBlock
) {
245 return EFI_INVALID_PARAMETER
;
249 (VOID
*)(UINTN
)(PrivateData
->StartingAddr
+ MultU64x32 (Lba
, PrivateData
->Media
.BlockSize
)),
259 Flush the Block Device.
261 @param[in] This Indicates a pointer to the calling context.
263 @retval EFI_SUCCESS All outstanding data was written to the device.
264 @retval EFI_DEVICE_ERROR The device reported an error while writting
266 @retval EFI_NO_MEDIA There is no media in the device.
271 RamDiskBlkIoFlushBlocks (
272 IN EFI_BLOCK_IO_PROTOCOL
*This
280 Resets the block device hardware.
282 @param[in] This The pointer of EFI_BLOCK_IO2_PROTOCOL.
283 @param[in] ExtendedVerification The flag about if extend verificate.
285 @retval EFI_SUCCESS The device was reset.
286 @retval EFI_DEVICE_ERROR The block device is not functioning correctly
287 and could not be reset.
293 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
294 IN BOOLEAN ExtendedVerification
302 Reads the requested number of blocks from the device.
304 @param[in] This Indicates a pointer to the calling context.
305 @param[in] MediaId The media ID that the read request is for.
306 @param[in] Lba The starting logical block address to read
308 @param[in, out] Token A pointer to the token associated with the
310 @param[in] BufferSize The size of the Buffer in bytes. This must be
311 a multiple of the intrinsic block size of the
313 @param[out] Buffer A pointer to the destination buffer for the
314 data. The caller is responsible for either
315 having implicit or explicit ownership of the
318 @retval EFI_SUCCESS The read request was queued if Token->Event
319 is not NULL. The data was read correctly from
320 the device if the Token->Event is NULL.
321 @retval EFI_DEVICE_ERROR The device reported an error while attempting
322 to perform the read operation.
323 @retval EFI_NO_MEDIA There is no media in the device.
324 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
325 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
326 the intrinsic block size of the device.
327 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
328 valid, or the buffer is not on proper
330 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
336 RamDiskBlkIo2ReadBlocksEx (
337 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
340 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
345 RAM_DISK_PRIVATE_DATA
*PrivateData
;
348 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO2 (This
);
350 Status
= RamDiskBlkIoReadBlocks (
351 &PrivateData
->BlockIo
,
357 if (EFI_ERROR (Status
)) {
362 // If caller's event is given, signal it after the memory read completes.
364 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
365 Token
->TransactionStatus
= EFI_SUCCESS
;
366 gBS
->SignalEvent (Token
->Event
);
374 Writes a specified number of blocks to the device.
376 @param[in] This Indicates a pointer to the calling context.
377 @param[in] MediaId The media ID that the write request is for.
378 @param[in] Lba The starting logical block address to be
379 written. The caller is responsible for
380 writing to only legitimate locations.
381 @param[in, out] Token A pointer to the token associated with the
383 @param[in] BufferSize The size in bytes of Buffer. This must be a
384 multiple of the intrinsic block size of the
386 @param[in] Buffer A pointer to the source buffer for the data.
388 @retval EFI_SUCCESS The write request was queued if Event is not
389 NULL. The data was written correctly to the
390 device if the Event is NULL.
391 @retval EFI_WRITE_PROTECTED The device cannot be written to.
392 @retval EFI_NO_MEDIA There is no media in the device.
393 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
394 @retval EFI_DEVICE_ERROR The device reported an error while attempting
395 to perform the write operation.
396 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
397 the intrinsic block size of the device.
398 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
399 valid, or the buffer is not on proper
401 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
407 RamDiskBlkIo2WriteBlocksEx (
408 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
411 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
416 RAM_DISK_PRIVATE_DATA
*PrivateData
;
419 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO2 (This
);
421 Status
= RamDiskBlkIoWriteBlocks (
422 &PrivateData
->BlockIo
,
428 if (EFI_ERROR (Status
)) {
433 // If caller's event is given, signal it after the memory write completes.
435 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
436 Token
->TransactionStatus
= EFI_SUCCESS
;
437 gBS
->SignalEvent (Token
->Event
);
445 Flushes all modified data to a physical block device.
447 @param[in] This Indicates a pointer to the calling context.
448 @param[in, out] Token A pointer to the token associated with the
451 @retval EFI_SUCCESS The flush request was queued if Event is not
452 NULL. All outstanding data was written
453 correctly to the device if the Event is NULL.
454 @retval EFI_DEVICE_ERROR The device reported an error while attempting
456 @retval EFI_WRITE_PROTECTED The device cannot be written to.
457 @retval EFI_NO_MEDIA There is no media in the device.
458 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
459 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
465 RamDiskBlkIo2FlushBlocksEx (
466 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
467 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
470 RAM_DISK_PRIVATE_DATA
*PrivateData
;
472 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO2 (This
);
474 if (TRUE
== PrivateData
->Media
.ReadOnly
) {
475 return EFI_WRITE_PROTECTED
;
479 // If caller's event is given, signal it directly.
481 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
482 Token
->TransactionStatus
= EFI_SUCCESS
;
483 gBS
->SignalEvent (Token
->Event
);