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
37 Initialize the BlockIO & BlockIO2 protocol of a RAM disk device.
39 @param[in] PrivateData Points to RAM disk private data.
44 IN RAM_DISK_PRIVATE_DATA
*PrivateData
47 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
48 EFI_BLOCK_IO2_PROTOCOL
*BlockIo2
;
49 EFI_BLOCK_IO_MEDIA
*Media
;
52 BlockIo
= &PrivateData
->BlockIo
;
53 BlockIo2
= &PrivateData
->BlockIo2
;
54 Media
= &PrivateData
->Media
;
56 CopyMem (BlockIo
, &mRamDiskBlockIoTemplate
, sizeof (EFI_BLOCK_IO_PROTOCOL
));
57 CopyMem (BlockIo2
, &mRamDiskBlockIo2Template
, sizeof (EFI_BLOCK_IO2_PROTOCOL
));
59 BlockIo
->Media
= Media
;
60 BlockIo2
->Media
= Media
;
61 Media
->RemovableMedia
= FALSE
;
62 Media
->MediaPresent
= TRUE
;
63 Media
->LogicalPartition
= FALSE
;
64 Media
->ReadOnly
= FALSE
;
65 Media
->WriteCaching
= FALSE
;
67 for (Media
->BlockSize
= RAM_DISK_DEFAULT_BLOCK_SIZE
;
68 Media
->BlockSize
>= 1;
69 Media
->BlockSize
= Media
->BlockSize
>> 1)
71 Media
->LastBlock
= DivU64x32Remainder (PrivateData
->Size
, Media
->BlockSize
, &Remainder
) - 1;
77 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
104 Read BufferSize bytes from Lba into Buffer.
106 @param[in] This Indicates a pointer to the calling context.
107 @param[in] MediaId Id of the media, changes every time the media is
109 @param[in] Lba The starting Logical Block Address to read from.
110 @param[in] BufferSize Size of Buffer, must be a multiple of device block
112 @param[out] Buffer A pointer to the destination buffer for the data.
113 The caller is responsible for either having
114 implicit or explicit ownership of the buffer.
116 @retval EFI_SUCCESS The data was read correctly from the device.
117 @retval EFI_DEVICE_ERROR The device reported an error while performing
119 @retval EFI_NO_MEDIA There is no media in the device.
120 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current
122 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
124 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
125 valid, or the buffer is not on proper alignment.
130 RamDiskBlkIoReadBlocks (
131 IN EFI_BLOCK_IO_PROTOCOL
*This
,
138 RAM_DISK_PRIVATE_DATA
*PrivateData
;
139 UINTN NumberOfBlocks
;
141 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO (This
);
143 if (MediaId
!= PrivateData
->Media
.MediaId
) {
144 return EFI_MEDIA_CHANGED
;
147 if (Buffer
== NULL
) {
148 return EFI_INVALID_PARAMETER
;
151 if (BufferSize
== 0) {
155 if ((BufferSize
% PrivateData
->Media
.BlockSize
) != 0) {
156 return EFI_BAD_BUFFER_SIZE
;
159 if (Lba
> PrivateData
->Media
.LastBlock
) {
160 return EFI_INVALID_PARAMETER
;
163 NumberOfBlocks
= BufferSize
/ PrivateData
->Media
.BlockSize
;
164 if ((Lba
+ NumberOfBlocks
- 1) > PrivateData
->Media
.LastBlock
) {
165 return EFI_INVALID_PARAMETER
;
170 (VOID
*)(UINTN
)(PrivateData
->StartingAddr
+ MultU64x32 (Lba
, PrivateData
->Media
.BlockSize
)),
178 Write BufferSize bytes from Lba into Buffer.
180 @param[in] This Indicates a pointer to the calling context.
181 @param[in] MediaId The media ID that the write request is for.
182 @param[in] Lba The starting logical block address to be written.
183 The caller is responsible for writing to only
184 legitimate locations.
185 @param[in] BufferSize Size of Buffer, must be a multiple of device block
187 @param[in] Buffer A pointer to the source buffer for the data.
189 @retval EFI_SUCCESS The data was written correctly to the device.
190 @retval EFI_WRITE_PROTECTED The device can not be written to.
191 @retval EFI_DEVICE_ERROR The device reported an error while performing
193 @retval EFI_NO_MEDIA There is no media in the device.
194 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current
196 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
198 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
199 valid, or the buffer is not on proper alignment.
204 RamDiskBlkIoWriteBlocks (
205 IN EFI_BLOCK_IO_PROTOCOL
*This
,
212 RAM_DISK_PRIVATE_DATA
*PrivateData
;
213 UINTN NumberOfBlocks
;
215 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO (This
);
217 if (MediaId
!= PrivateData
->Media
.MediaId
) {
218 return EFI_MEDIA_CHANGED
;
221 if (TRUE
== PrivateData
->Media
.ReadOnly
) {
222 return EFI_WRITE_PROTECTED
;
225 if (Buffer
== NULL
) {
226 return EFI_INVALID_PARAMETER
;
229 if (BufferSize
== 0) {
233 if ((BufferSize
% PrivateData
->Media
.BlockSize
) != 0) {
234 return EFI_BAD_BUFFER_SIZE
;
237 if (Lba
> PrivateData
->Media
.LastBlock
) {
238 return EFI_INVALID_PARAMETER
;
241 NumberOfBlocks
= BufferSize
/ PrivateData
->Media
.BlockSize
;
242 if ((Lba
+ NumberOfBlocks
- 1) > PrivateData
->Media
.LastBlock
) {
243 return EFI_INVALID_PARAMETER
;
247 (VOID
*)(UINTN
)(PrivateData
->StartingAddr
+ MultU64x32 (Lba
, PrivateData
->Media
.BlockSize
)),
256 Flush the Block Device.
258 @param[in] This Indicates a pointer to the calling context.
260 @retval EFI_SUCCESS All outstanding data was written to the device.
261 @retval EFI_DEVICE_ERROR The device reported an error while writting
263 @retval EFI_NO_MEDIA There is no media in the device.
268 RamDiskBlkIoFlushBlocks (
269 IN EFI_BLOCK_IO_PROTOCOL
*This
276 Resets the block device hardware.
278 @param[in] This The pointer of EFI_BLOCK_IO2_PROTOCOL.
279 @param[in] ExtendedVerification The flag about if extend verificate.
281 @retval EFI_SUCCESS The device was reset.
282 @retval EFI_DEVICE_ERROR The block device is not functioning correctly
283 and could not be reset.
289 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
290 IN BOOLEAN ExtendedVerification
297 Reads the requested number of blocks from the device.
299 @param[in] This Indicates a pointer to the calling context.
300 @param[in] MediaId The media ID that the read request is for.
301 @param[in] Lba The starting logical block address to read
303 @param[in, out] Token A pointer to the token associated with the
305 @param[in] BufferSize The size of the Buffer in bytes. This must be
306 a multiple of the intrinsic block size of the
308 @param[out] Buffer A pointer to the destination buffer for the
309 data. The caller is responsible for either
310 having implicit or explicit ownership of the
313 @retval EFI_SUCCESS The read request was queued if Token->Event
314 is not NULL. The data was read correctly from
315 the device if the Token->Event is NULL.
316 @retval EFI_DEVICE_ERROR The device reported an error while attempting
317 to perform the read operation.
318 @retval EFI_NO_MEDIA There is no media in the device.
319 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
320 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
321 the intrinsic block size of the device.
322 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
323 valid, or the buffer is not on proper
325 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
331 RamDiskBlkIo2ReadBlocksEx (
332 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
335 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
340 RAM_DISK_PRIVATE_DATA
*PrivateData
;
343 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO2 (This
);
345 Status
= RamDiskBlkIoReadBlocks (
346 &PrivateData
->BlockIo
,
352 if (EFI_ERROR (Status
)) {
357 // If caller's event is given, signal it after the memory read completes.
359 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
360 Token
->TransactionStatus
= EFI_SUCCESS
;
361 gBS
->SignalEvent (Token
->Event
);
368 Writes a specified number of blocks to the device.
370 @param[in] This Indicates a pointer to the calling context.
371 @param[in] MediaId The media ID that the write request is for.
372 @param[in] Lba The starting logical block address to be
373 written. The caller is responsible for
374 writing to only legitimate locations.
375 @param[in, out] Token A pointer to the token associated with the
377 @param[in] BufferSize The size in bytes of Buffer. This must be a
378 multiple of the intrinsic block size of the
380 @param[in] Buffer A pointer to the source buffer for the data.
382 @retval EFI_SUCCESS The write request was queued if Event is not
383 NULL. The data was written correctly to the
384 device if the Event is NULL.
385 @retval EFI_WRITE_PROTECTED The device cannot be written to.
386 @retval EFI_NO_MEDIA There is no media in the device.
387 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
388 @retval EFI_DEVICE_ERROR The device reported an error while attempting
389 to perform the write operation.
390 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
391 the intrinsic block size of the device.
392 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
393 valid, or the buffer is not on proper
395 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
401 RamDiskBlkIo2WriteBlocksEx (
402 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
405 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
,
410 RAM_DISK_PRIVATE_DATA
*PrivateData
;
413 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO2 (This
);
415 Status
= RamDiskBlkIoWriteBlocks (
416 &PrivateData
->BlockIo
,
422 if (EFI_ERROR (Status
)) {
427 // If caller's event is given, signal it after the memory write completes.
429 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
430 Token
->TransactionStatus
= EFI_SUCCESS
;
431 gBS
->SignalEvent (Token
->Event
);
438 Flushes all modified data to a physical block device.
440 @param[in] This Indicates a pointer to the calling context.
441 @param[in, out] Token A pointer to the token associated with the
444 @retval EFI_SUCCESS The flush request was queued if Event is not
445 NULL. All outstanding data was written
446 correctly to the device if the Event is NULL.
447 @retval EFI_DEVICE_ERROR The device reported an error while attempting
449 @retval EFI_WRITE_PROTECTED The device cannot be written to.
450 @retval EFI_NO_MEDIA There is no media in the device.
451 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
452 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
458 RamDiskBlkIo2FlushBlocksEx (
459 IN EFI_BLOCK_IO2_PROTOCOL
*This
,
460 IN OUT EFI_BLOCK_IO2_TOKEN
*Token
463 RAM_DISK_PRIVATE_DATA
*PrivateData
;
465 PrivateData
= RAM_DISK_PRIVATE_FROM_BLKIO2 (This
);
467 if (TRUE
== PrivateData
->Media
.ReadOnly
) {
468 return EFI_WRITE_PROTECTED
;
472 // If caller's event is given, signal it directly.
474 if ((Token
!= NULL
) && (Token
->Event
!= NULL
)) {
475 Token
->TransactionStatus
= EFI_SUCCESS
;
476 gBS
->SignalEvent (Token
->Event
);