source: bootcd/isolinux/syslinux-6.03/efi/fio.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 7.0 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
4 *   Copyright 2012 Intel Corporation; author: H. Peter Anvin
5 *   Chandramouli Narayanan
6 *
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.
12 *
13 * ----------------------------------------------------------------------- */
14
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
18 *
19 */
20#include "efi.h"
21#include "fio.h"
22
23/* Variables that need to be exported
24 * efi_errno - maintains the errors from EFI calls to display error messages.
25 */
26EFI_STATUS efi_errno = EFI_SUCCESS;
27
28/* Locals
29 * vol_root - handle to the root device for file operations
30 */
31static EFI_FILE_HANDLE vol_root;
32
33/* Table of UEFI error messages to be indexed with the EFI errno
34 * Update error message list as needed
35 */
36static 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"
62};
63
64static UINTN nerrs = sizeof(uefi_errmsg)/sizeof(CHAR16 *);
65
66
67/* Generic write error message; there is no gnu lib api to write to StdErr
68 * For now, everything goes ConOut
69 */
70void efi_printerr(
71    CHAR16   *fmt,
72    ...
73    )
74{
75    va_list     args;
76    va_start (args, fmt);
77    VPrint (fmt, args);
78    va_end (args);
79}
80
81/* Simple console logger of efi-specific error messages. It uses
82 * gnu-efi library Print function to do the job.
83 */
84
85void efi_perror(CHAR16 *prog)
86{
87        /* Ensure that the err number lies within range
88         * Beware: unsigned comparisons fail on efi, signed comparisons work
89         */
90        if (EFI_ERROR(efi_errno) && (INTN)efi_errno < (INTN)nerrs)
91                efi_printerr(L"%s: %s\n", prog, uefi_errmsg[efi_errno]);
92}
93
94/* Write to UEFI ConOut */
95void efi_printout(
96    CHAR16   *fmt,
97    ...
98    )
99{
100    va_list     args;
101    va_start (args, fmt);
102    VPrint (fmt, args);
103    va_end (args);
104}
105
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.
112 *
113 */
114
115EFI_STATUS efi_set_volroot(EFI_HANDLE device_handle)
116{
117        vol_root = LibOpenRoot(device_handle);
118        if (!vol_root) {
119                return EFI_DEVICE_ERROR;
120        }
121        return EFI_SUCCESS;
122}
123
124/* File operations using EFI runtime services */
125
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
130 *
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.
133 *
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()
141 */
142EFI_FILE_HANDLE efi_open(CHAR16 *file, UINT64 mode)
143{
144        /* initialize with NULL handle since EFI open returns bogus */
145        EFI_FILE_HANDLE fd = NULL;
146
147        ASSERT(vol_root);
148
149        /* Note that the attributes parameter is none for now */
150        efi_errno = uefi_call_wrapper(vol_root->Open,
151                                        5,
152                                        vol_root,
153                                        &fd,
154                                        file,
155                                        mode,
156                                        0);
157        return fd;
158}
159
160/*
161 * read/write wrapper functions for UEFI
162 *
163 * Read or write the specified number of bytes starting at the
164 * offset specified.
165 *
166 * Returns:
167 * number of bytes read/written on success
168 * -1 on error
169 */
170/* Wrapper function to read from a file */
171size_t efi_xpread(EFI_FILE_HANDLE fd, void *buf, size_t count, off_t offset)
172{
173        ASSERT(fd);
174        efi_errno = uefi_call_wrapper(fd->SetPosition,
175                                        2,
176                                    fd,
177                                    offset);
178        if (EFI_ERROR(efi_errno)) return -1;
179        efi_errno = uefi_call_wrapper(fd->Read,
180                                        3,
181                                    fd,
182                                    &count,
183                                        buf);
184        if (EFI_ERROR(efi_errno)) return -1;
185        return count;
186}
187
188/* Wrapper function to write */
189size_t efi_xpwrite(EFI_FILE_HANDLE fd, void *buf, size_t count, off_t offset)
190{
191        ASSERT(fd);
192        efi_errno = uefi_call_wrapper(fd->SetPosition,
193                                        2,
194                                    fd,
195                                    offset);
196        if (EFI_ERROR(efi_errno)) return -1;
197        efi_errno = uefi_call_wrapper(fd->Write,
198                                        3,
199                                    fd,
200                                    &count,
201                                        buf);
202        if (EFI_ERROR(efi_errno)) return -1;
203        return count;
204}
205
206/* For an open handle, return the generic file info excluding
207 * the variable-length filename in the EFI_FILE_INFO structure.
208 */
209int efi_fstat(EFI_FILE_HANDLE fd, EFI_FILE_INFO *st)
210{
211        EFI_FILE_INFO *finfo;
212
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;
219        }
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;
223}
224
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?
230 */
231void efi_set_attributes(EFI_FILE_HANDLE fd)
232{
233        EFI_FILE_INFO *finfo;
234
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,
241                                        4,
242                                        fd,
243                                        &GenericFileInfo,
244                                        finfo->Size,
245                                        finfo);
246                FreePool(finfo);
247        } else efi_errno = EFI_NOT_FOUND;
248}
249
250void efi_clear_attributes(EFI_FILE_HANDLE fd)
251{
252        EFI_FILE_INFO *finfo;
253
254        ASSERT(fd);
255        finfo = LibFileInfo(fd);
256        if (finfo) {
257                finfo->Attribute = 0; /* no attributes */
258                efi_errno = uefi_call_wrapper(fd->SetInfo,
259                                        4,
260                                        fd,
261                                        &GenericFileInfo,
262                                        finfo->Size,
263                                        finfo);
264                FreePool(finfo);
265        } else efi_errno = EFI_NOT_FOUND;
266}
267
268/* Implement the sync operation using the EFI Flush file operation*/
269void efi_sync(EFI_FILE_HANDLE fd)
270{
271        ASSERT(fd);
272        efi_errno = uefi_call_wrapper(fd->Flush, 1, fd);
273        return;
274}
275
276/* Close the file */
277void efi_close(EFI_FILE_HANDLE fd)
278{
279
280        ASSERT(fd);
281        efi_errno = uefi_call_wrapper(fd->Close, 1, fd);
282        return;
283}
Note: See TracBrowser for help on using the repository browser.