]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/FileSystem/BootMonFs/BootMonFsReadWrite.c
ArmPlatformPkg/BootMonFs: Fix error codes returned by Open() and Read()
[mirror_edk2.git] / ArmPlatformPkg / FileSystem / BootMonFs / BootMonFsReadWrite.c
1 /** @file
2 *
3 * Copyright (c) 2012-2014, ARM Limited. All rights reserved.
4 *
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 <Protocol/SimpleFileSystem.h>
16 #include <Library/UefiLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/MemoryAllocationLib.h>
19 #include <Library/DebugLib.h>
20
21 #include "BootMonFsInternal.h"
22
23 /**
24 Read data from an open file.
25
26 @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
27 is the file handle to read data from.
28 @param[in out] BufferSize On input, the size of the Buffer. On output, the
29 amount of data returned in Buffer. In both cases,
30 the size is measured in bytes.
31 @param[out] Buffer The buffer into which the data is read.
32
33 @retval EFI_SUCCESS The data was read.
34 @retval EFI_DEVICE_ERROR On entry, the current file position is
35 beyond the end of the file, or the device
36 reported an error while performing the read
37 operation.
38 @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
39 **/
40 EFIAPI
41 EFI_STATUS
42 BootMonFsReadFile (
43 IN EFI_FILE_PROTOCOL *This,
44 IN OUT UINTN *BufferSize,
45 OUT VOID *Buffer
46 )
47 {
48 BOOTMON_FS_INSTANCE *Instance;
49 BOOTMON_FS_FILE *File;
50 EFI_DISK_IO_PROTOCOL *DiskIo;
51 EFI_BLOCK_IO_MEDIA *Media;
52 UINT64 FileStart;
53 EFI_STATUS Status;
54 UINTN RemainingFileSize;
55
56 // Ensure the file has been written in Flash before reading it.
57 // This keeps the code simple and avoids having to manage a non-flushed file.
58 BootMonFsFlushFile (This);
59
60 File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
61 if (File == NULL) {
62 return EFI_INVALID_PARAMETER;
63 }
64
65 Instance = File->Instance;
66 DiskIo = Instance->DiskIo;
67 Media = Instance->Media;
68 FileStart = (Media->LowestAlignedLba + File->HwDescription.BlockStart) * Media->BlockSize;
69
70 if (File->Position >= File->HwDescription.Region[0].Size) {
71 // The entire file has been read or the position has been
72 // set past the end of the file.
73 *BufferSize = 0;
74 if (File->Position > File->HwDescription.Region[0].Size) {
75 return EFI_DEVICE_ERROR;
76 } else {
77 return EFI_SUCCESS;
78 }
79 }
80
81 // This driver assumes that the entire file is in region 0.
82 RemainingFileSize = File->HwDescription.Region[0].Size - File->Position;
83
84 // If read would go past end of file, truncate the read
85 if (*BufferSize > RemainingFileSize) {
86 *BufferSize = RemainingFileSize;
87 }
88
89 Status = DiskIo->ReadDisk (
90 DiskIo,
91 Media->MediaId,
92 FileStart + File->Position,
93 *BufferSize,
94 Buffer
95 );
96 if (EFI_ERROR (Status)) {
97 *BufferSize = 0;
98 }
99
100 File->Position += *BufferSize;
101
102 return Status;
103 }
104
105 // Inserts an entry into the write chain
106 EFIAPI
107 EFI_STATUS
108 BootMonFsWriteFile (
109 IN EFI_FILE_PROTOCOL *This,
110 IN OUT UINTN *BufferSize,
111 IN VOID *Buffer
112 )
113 {
114 BOOTMON_FS_FILE *File;
115 BOOTMON_FS_FILE_REGION *Region;
116
117 File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
118 if (File == NULL) {
119 return EFI_INVALID_PARAMETER;
120 }
121
122 if (!(File->OpenMode & EFI_FILE_MODE_WRITE)) {
123 return EFI_ACCESS_DENIED;
124 }
125
126 // Allocate and initialize the memory region
127 Region = (BOOTMON_FS_FILE_REGION*)AllocateZeroPool (sizeof (BOOTMON_FS_FILE_REGION));
128 if (Region == NULL) {
129 return EFI_OUT_OF_RESOURCES;
130 }
131
132 Region->Buffer = AllocateCopyPool (*BufferSize, Buffer);
133 if (Region->Buffer == NULL) {
134 FreePool (Region);
135 return EFI_OUT_OF_RESOURCES;
136 }
137
138 Region->Size = *BufferSize;
139
140 Region->Offset = File->Position;
141
142 InsertTailList (&File->RegionToFlushLink, &Region->Link);
143
144 File->Position += *BufferSize;
145
146 return EFI_SUCCESS;
147 }
148
149 EFIAPI
150 EFI_STATUS
151 BootMonFsSetPosition (
152 IN EFI_FILE_PROTOCOL *This,
153 IN UINT64 Position
154 )
155 {
156 BOOTMON_FS_FILE *File;
157
158 File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
159
160 // UEFI Spec section 12.5:
161 // "Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to
162 // be set to the end of the file."
163 if (Position == 0xFFFFFFFFFFFFFFFF) {
164 File->Position = BootMonFsGetImageLength (File);
165 } else {
166 // NB: Seeking past the end of the file is valid.
167 File->Position = Position;
168 }
169
170 return EFI_SUCCESS;
171 }
172
173 EFIAPI
174 EFI_STATUS
175 BootMonFsGetPosition (
176 IN EFI_FILE_PROTOCOL *This,
177 OUT UINT64 *Position
178 ) {
179 BOOTMON_FS_FILE *File;
180
181 File = BOOTMON_FS_FILE_FROM_FILE_THIS (This);
182
183 *Position = File->Position;
184 return EFI_SUCCESS;
185 }