mk/efi.mk: Add libefi.a dependency
[syslinux.git] / efi / fio.c
blobf56cd5b4719bf2de1b90a1c46e3d30a43314c46d
1 /* ----------------------------------------------------------------------- *
3 * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
4 * Copyright 2012 Intel Corporation; author: H. Peter Anvin
5 * Chandramouli Narayanan
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
10 * Boston MA 02111-1307, USA; either version 2 of the License, or
11 * (at your option) any later version; incorporated herein by reference.
13 * ----------------------------------------------------------------------- */
15 /* Miscellaneous functions for UEFI support
16 * We assume that EFI library initialization has completed
17 * and we have access to the global EFI exported variables
20 #include "efi.h"
21 #include "fio.h"
23 /* Variables that need to be exported
24 * efi_errno - maintains the errors from EFI calls to display error messages.
26 EFI_STATUS efi_errno = EFI_SUCCESS;
28 /* Locals
29 * vol_root - handle to the root device for file operations
31 static EFI_FILE_HANDLE vol_root;
33 /* Table of UEFI error messages to be indexed with the EFI errno
34 * Update error message list as needed
36 static CHAR16 *uefi_errmsg[] = {
37 L"EFI_UNDEFINED", /* should not get here */
38 L"EFI_LOAD_ERROR",
39 L"EFI_INVALID_PARAMETER",
40 L"EFI_UNSUPPORTED",
41 L"EFI_BAD_BUFFER_SIZE",
42 L"EFI_BUFFER_TOO_SMALL",
43 L"EFI_NOT_READY",
44 L"EFI_DEVICE_ERROR",
45 L"EFI_WRITE_PROTECTED",
46 L"EFI_OUT_OF_RESOURCES",
47 L"EFI_VOLUME_CORRUPTED",
48 L"EFI_VOLUME_FULL",
49 L"EFI_NO_MEDIA",
50 L"EFI_MEDIA_CHANGED",
51 L"EFI_NOT_FOUND",
52 L"EFI_ACCESS_DENIED",
53 L"EFI_NO_RESPONSE",
54 L"EFI_NO_MAPPING",
55 L"EFI_TIMEOUT",
56 L"EFI_NOT_STARTED",
57 L"EFI_ALREADY_STARTED",
58 L"EFI_ABORTED",
59 L"EFI_ICMP_ERROR",
60 L"EFI_TFTP_ERROR",
61 L"EFI_PROTOCOL_ERROR"
64 static UINTN nerrs = sizeof(uefi_errmsg)/sizeof(CHAR16 *);
67 /* Generic write error message; there is no gnu lib api to write to StdErr
68 * For now, everything goes ConOut
70 void efi_printerr(
71 CHAR16 *fmt,
72 ...
75 va_list args;
76 va_start (args, fmt);
77 VPrint (fmt, args);
78 va_end (args);
81 /* Simple console logger of efi-specific error messages. It uses
82 * gnu-efi library Print function to do the job.
85 void efi_perror(CHAR16 *prog)
87 /* Ensure that the err number lies within range
88 * Beware: unsigned comparisons fail on efi, signed comparisons work
90 if (EFI_ERROR(efi_errno) && (INTN)efi_errno < (INTN)nerrs)
91 efi_printerr(L"%s: %s\n", prog, uefi_errmsg[efi_errno]);
94 /* Write to UEFI ConOut */
95 void efi_printout(
96 CHAR16 *fmt,
97 ...
100 va_list args;
101 va_start (args, fmt);
102 VPrint (fmt, args);
103 va_end (args);
106 /* IMPORTANT:
107 * efi_setvol_root() needs to be called from efi main.
108 * The rest of the ADV support relies on the file i/o environment
109 * setup here. In order to use the EFI file support, we need
110 * to set up the volume root. Subsequent file operations need the root to
111 * access the interface routines.
115 EFI_STATUS efi_set_volroot(EFI_HANDLE device_handle)
117 vol_root = LibOpenRoot(device_handle);
118 if (!vol_root) {
119 return EFI_DEVICE_ERROR;
121 return EFI_SUCCESS;
124 /* File operations using EFI runtime services */
126 /* Open the file using EFI runtime service
127 * Opening a file in EFI requires a handle to the device
128 * root in order to use the interface to the file operations supported by UEFI.
129 * For now, assume device volume root handle from the loaded image
131 * Return a valid handle if open succeeded and null otherwise.
132 * UEFI returns a bogus handle on error, so return null handle on error.
134 * TODO:
135 * 1. Validate the assumption about the root device
136 * 2. Can EFI open a file with full path name specification?
137 * 3. Look into gnu-efi helper functions for dealing with device path/file path
138 * 4. Consider utilizing EFI file open attributes.
139 * 5. In EFI, file attributes can be specified only at the time of creation.
140 * How do we support the equivalent of set_attributes() and clear_attributes()
142 EFI_FILE_HANDLE efi_open(CHAR16 *file, UINT64 mode)
144 /* initialize with NULL handle since EFI open returns bogus */
145 EFI_FILE_HANDLE fd = NULL;
147 ASSERT(vol_root);
149 /* Note that the attributes parameter is none for now */
150 efi_errno = uefi_call_wrapper(vol_root->Open,
152 vol_root,
153 &fd,
154 file,
155 mode,
157 return fd;
161 * read/write wrapper functions for UEFI
163 * Read or write the specified number of bytes starting at the
164 * offset specified.
166 * Returns:
167 * number of bytes read/written on success
168 * -1 on error
170 /* Wrapper function to read from a file */
171 size_t efi_xpread(EFI_FILE_HANDLE fd, void *buf, size_t count, off_t offset)
173 ASSERT(fd);
174 efi_errno = uefi_call_wrapper(fd->SetPosition,
177 offset);
178 if (EFI_ERROR(efi_errno)) return -1;
179 efi_errno = uefi_call_wrapper(fd->Read,
182 &count,
183 buf);
184 if (EFI_ERROR(efi_errno)) return -1;
185 return count;
188 /* Wrapper function to write */
189 size_t efi_xpwrite(EFI_FILE_HANDLE fd, void *buf, size_t count, off_t offset)
191 ASSERT(fd);
192 efi_errno = uefi_call_wrapper(fd->SetPosition,
195 offset);
196 if (EFI_ERROR(efi_errno)) return -1;
197 efi_errno = uefi_call_wrapper(fd->Write,
200 &count,
201 buf);
202 if (EFI_ERROR(efi_errno)) return -1;
203 return count;
206 /* For an open handle, return the generic file info excluding
207 * the variable-length filename in the EFI_FILE_INFO structure.
209 int efi_fstat(EFI_FILE_HANDLE fd, EFI_FILE_INFO *st)
211 EFI_FILE_INFO *finfo;
213 ASSERT(fd);
214 finfo = LibFileInfo(fd);
215 if (finfo) {
216 uefi_call_wrapper(BS->CopyMem, 3, (VOID *)st, (VOID *)finfo, SIZE_OF_EFI_FILE_INFO);
217 FreePool(finfo);
218 return 0;
220 /* gnu-efi lib does not return EFI status; export a generic device error for now */
221 efi_errno = EFI_DEVICE_ERROR;
222 return -1;
225 /* set/clear_attributes()
226 * Currently handles only VFAT filesystem
227 * TODO:
228 * 1. Assumes VFAT file system.
229 * 2. How do we support other file systems?
231 void efi_set_attributes(EFI_FILE_HANDLE fd)
233 EFI_FILE_INFO *finfo;
235 ASSERT(fd);
236 finfo = LibFileInfo(fd);
237 if (finfo) {
238 /* Hidden+System+Readonly */
239 finfo->Attribute = EFI_FILE_READ_ONLY|EFI_FILE_HIDDEN|EFI_FILE_SYSTEM;
240 efi_errno = uefi_call_wrapper(fd->SetInfo,
243 &GenericFileInfo,
244 finfo->Size,
245 finfo);
246 FreePool(finfo);
247 } else efi_errno = EFI_NOT_FOUND;
250 void efi_clear_attributes(EFI_FILE_HANDLE fd)
252 EFI_FILE_INFO *finfo;
254 ASSERT(fd);
255 finfo = LibFileInfo(fd);
256 if (finfo) {
257 finfo->Attribute = 0; /* no attributes */
258 efi_errno = uefi_call_wrapper(fd->SetInfo,
261 &GenericFileInfo,
262 finfo->Size,
263 finfo);
264 FreePool(finfo);
265 } else efi_errno = EFI_NOT_FOUND;
268 /* Implement the sync operation using the EFI Flush file operation*/
269 void efi_sync(EFI_FILE_HANDLE fd)
271 ASSERT(fd);
272 efi_errno = uefi_call_wrapper(fd->Flush, 1, fd);
273 return;
276 /* Close the file */
277 void efi_close(EFI_FILE_HANDLE fd)
280 ASSERT(fd);
281 efi_errno = uefi_call_wrapper(fd->Close, 1, fd);
282 return;