]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c
MdeModulePkg: Add RamDiskDxe driver implementation
[mirror_edk2.git] / MdeModulePkg / Universal / Disk / RamDiskDxe / RamDiskBlockIo.c
1 /** @file
2 Produce EFI_BLOCK_IO_PROTOCOL on a RAM disk device.
3
4 Copyright (c) 2016, 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
9
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.
12
13 **/
14
15 #include "RamDiskImpl.h"
16
17 //
18 // The EFI_BLOCK_IO_PROTOCOL instances that is installed onto the handle
19 // for newly registered RAM disks
20 //
21 EFI_BLOCK_IO_PROTOCOL mRamDiskBlockIoTemplate = {
22 EFI_BLOCK_IO_PROTOCOL_REVISION,
23 (EFI_BLOCK_IO_MEDIA *) 0,
24 RamDiskBlkIoReset,
25 RamDiskBlkIoReadBlocks,
26 RamDiskBlkIoWriteBlocks,
27 RamDiskBlkIoFlushBlocks
28 };
29
30
31 /**
32 Initialize the BlockIO protocol of a RAM disk device.
33
34 @param[in] PrivateData Points to RAM disk private data.
35
36 **/
37 VOID
38 RamDiskInitBlockIo (
39 IN RAM_DISK_PRIVATE_DATA *PrivateData
40 )
41 {
42 EFI_BLOCK_IO_PROTOCOL *BlockIo;
43 EFI_BLOCK_IO_MEDIA *Media;
44
45 BlockIo = &PrivateData->BlockIo;
46 Media = &PrivateData->Media;
47
48 CopyMem (BlockIo, &mRamDiskBlockIoTemplate, sizeof (EFI_BLOCK_IO_PROTOCOL));
49
50 BlockIo->Media = Media;
51 Media->RemovableMedia = FALSE;
52 Media->MediaPresent = TRUE;
53 Media->LogicalPartition = FALSE;
54 Media->ReadOnly = FALSE;
55 Media->WriteCaching = FALSE;
56 Media->BlockSize = RAM_DISK_BLOCK_SIZE;
57 Media->LastBlock = DivU64x32 (
58 PrivateData->Size + RAM_DISK_BLOCK_SIZE - 1,
59 RAM_DISK_BLOCK_SIZE
60 ) - 1;
61 }
62
63
64 /**
65 Reset the Block Device.
66
67 @param This Indicates a pointer to the calling context.
68 @param ExtendedVerification Driver may perform diagnostics on reset.
69
70 @retval EFI_SUCCESS The device was reset.
71 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
72 not be reset.
73
74 **/
75 EFI_STATUS
76 EFIAPI
77 RamDiskBlkIoReset (
78 IN EFI_BLOCK_IO_PROTOCOL *This,
79 IN BOOLEAN ExtendedVerification
80 )
81 {
82 return EFI_SUCCESS;
83 }
84
85
86 /**
87 Read BufferSize bytes from Lba into Buffer.
88
89 @param[in] This Indicates a pointer to the calling context.
90 @param[in] MediaId Id of the media, changes every time the media is
91 replaced.
92 @param[in] Lba The starting Logical Block Address to read from.
93 @param[in] BufferSize Size of Buffer, must be a multiple of device block
94 size.
95 @param[out] Buffer A pointer to the destination buffer for the data.
96 The caller is responsible for either having
97 implicit or explicit ownership of the buffer.
98
99 @retval EFI_SUCCESS The data was read correctly from the device.
100 @retval EFI_DEVICE_ERROR The device reported an error while performing
101 the read.
102 @retval EFI_NO_MEDIA There is no media in the device.
103 @retval EFI_MEDIA_CHANGED The MediaId does not matched the current
104 device.
105 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
106 size of the device.
107 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
108 valid, or the buffer is not on proper alignment.
109
110 **/
111 EFI_STATUS
112 EFIAPI
113 RamDiskBlkIoReadBlocks (
114 IN EFI_BLOCK_IO_PROTOCOL *This,
115 IN UINT32 MediaId,
116 IN EFI_LBA Lba,
117 IN UINTN BufferSize,
118 OUT VOID *Buffer
119 )
120 {
121 RAM_DISK_PRIVATE_DATA *PrivateData;
122 UINTN NumberOfBlocks;
123
124 if (Buffer == NULL) {
125 return EFI_INVALID_PARAMETER;
126 }
127
128 if (BufferSize == 0) {
129 return EFI_SUCCESS;
130 }
131
132 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);
133
134 if (MediaId != PrivateData->Media.MediaId) {
135 return EFI_MEDIA_CHANGED;
136 }
137
138 if ((BufferSize % PrivateData->Media.BlockSize) != 0) {
139 return EFI_BAD_BUFFER_SIZE;
140 }
141
142 if (Lba > PrivateData->Media.LastBlock) {
143 return EFI_INVALID_PARAMETER;
144 }
145
146 NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;
147 if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {
148 return EFI_INVALID_PARAMETER;
149 }
150
151 CopyMem (
152 Buffer,
153 (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)),
154 BufferSize
155 );
156
157 return EFI_SUCCESS;
158 }
159
160
161 /**
162 Write BufferSize bytes from Lba into Buffer.
163
164 @param[in] This Indicates a pointer to the calling context.
165 @param[in] MediaId The media ID that the write request is for.
166 @param[in] Lba The starting logical block address to be written.
167 The caller is responsible for writing to only
168 legitimate locations.
169 @param[in] BufferSize Size of Buffer, must be a multiple of device block
170 size.
171 @param[in] Buffer A pointer to the source buffer for the data.
172
173 @retval EFI_SUCCESS The data was written correctly to the device.
174 @retval EFI_WRITE_PROTECTED The device can not be written to.
175 @retval EFI_DEVICE_ERROR The device reported an error while performing
176 the write.
177 @retval EFI_NO_MEDIA There is no media in the device.
178 @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current
179 device.
180 @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
181 size of the device.
182 @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
183 valid, or the buffer is not on proper alignment.
184
185 **/
186 EFI_STATUS
187 EFIAPI
188 RamDiskBlkIoWriteBlocks (
189 IN EFI_BLOCK_IO_PROTOCOL *This,
190 IN UINT32 MediaId,
191 IN EFI_LBA Lba,
192 IN UINTN BufferSize,
193 IN VOID *Buffer
194 )
195 {
196 RAM_DISK_PRIVATE_DATA *PrivateData;
197 UINTN NumberOfBlocks;
198
199 if (Buffer == NULL) {
200 return EFI_INVALID_PARAMETER;
201 }
202
203 if (BufferSize == 0) {
204 return EFI_SUCCESS;
205 }
206
207 PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);
208
209 if (MediaId != PrivateData->Media.MediaId) {
210 return EFI_MEDIA_CHANGED;
211 }
212
213 if (TRUE == PrivateData->Media.ReadOnly) {
214 return EFI_WRITE_PROTECTED;
215 }
216
217 if ((BufferSize % PrivateData->Media.BlockSize) != 0) {
218 return EFI_BAD_BUFFER_SIZE;
219 }
220
221 if (Lba > PrivateData->Media.LastBlock) {
222 return EFI_INVALID_PARAMETER;
223 }
224
225 NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;
226 if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {
227 return EFI_INVALID_PARAMETER;
228 }
229
230 CopyMem (
231 (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)),
232 Buffer,
233 BufferSize
234 );
235
236 return EFI_SUCCESS;
237 }
238
239
240 /**
241 Flush the Block Device.
242
243 @param[in] This Indicates a pointer to the calling context.
244
245 @retval EFI_SUCCESS All outstanding data was written to the device.
246 @retval EFI_DEVICE_ERROR The device reported an error while writting
247 back the data
248 @retval EFI_NO_MEDIA There is no media in the device.
249
250 **/
251 EFI_STATUS
252 EFIAPI
253 RamDiskBlkIoFlushBlocks (
254 IN EFI_BLOCK_IO_PROTOCOL *This
255 )
256 {
257 return EFI_SUCCESS;
258 }