iPXE
pxe_file.c
Go to the documentation of this file.
1 /** @file
2  *
3  * PXE FILE API
4  *
5  */
6 
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <errno.h>
10 #include <byteswap.h>
11 #include <ipxe/posix_io.h>
12 #include <ipxe/features.h>
13 #include <pxe.h>
14 #include <realmode.h>
15 
16 /*
17  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License as
21  * published by the Free Software Foundation; either version 2 of the
22  * License, or any later version.
23  *
24  * This program is distributed in the hope that it will be useful, but
25  * WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27  * General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32  * 02110-1301, USA.
33  *
34  * You can also choose to distribute this program under the terms of
35  * the Unmodified Binary Distribution Licence (as given in the file
36  * COPYING.UBDL), provided that you have satisfied its requirements.
37  */
38 
39 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
40 
42 
43 /**
44  * FILE OPEN
45  *
46  * @v file_open Pointer to a struct s_PXENV_FILE_OPEN
47  * @v s_PXENV_FILE_OPEN::FileName URL of file to open
48  * @ret #PXENV_EXIT_SUCCESS File was opened
49  * @ret #PXENV_EXIT_FAILURE File was not opened
50  * @ret s_PXENV_FILE_OPEN::Status PXE status code
51  * @ret s_PXENV_FILE_OPEN::FileHandle Handle of opened file
52  *
53  */
54 static PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ) {
55  const char *filename;
56  int fd;
57 
58  DBG ( "PXENV_FILE_OPEN" );
59 
60  /* Open specified filename */
61  filename = real_to_virt ( file_open->FileName.segment,
62  file_open->FileName.offset );
63  DBG ( " %s", filename );
64  fd = open ( filename );
65  if ( fd < 0 ) {
66  file_open->Status = PXENV_STATUS ( fd );
67  return PXENV_EXIT_FAILURE;
68  }
69  DBG ( " as file %d", fd );
70 
71  file_open->FileHandle = fd;
72  file_open->Status = PXENV_STATUS_SUCCESS;
73  return PXENV_EXIT_SUCCESS;
74 }
75 
76 /**
77  * FILE CLOSE
78  *
79  * @v file_close Pointer to a struct s_PXENV_FILE_CLOSE
80  * @v s_PXENV_FILE_CLOSE::FileHandle File handle
81  * @ret #PXENV_EXIT_SUCCESS File was closed
82  * @ret #PXENV_EXIT_FAILURE File was not closed
83  * @ret s_PXENV_FILE_CLOSE::Status PXE status code
84  *
85  */
86 static PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE *file_close ) {
87 
88  DBG ( "PXENV_FILE_CLOSE %d", file_close->FileHandle );
89 
90  close ( file_close->FileHandle );
91  file_close->Status = PXENV_STATUS_SUCCESS;
92  return PXENV_EXIT_SUCCESS;
93 }
94 
95 /**
96  * FILE SELECT
97  *
98  * @v file_select Pointer to a struct s_PXENV_FILE_SELECT
99  * @v s_PXENV_FILE_SELECT::FileHandle File handle
100  * @ret #PXENV_EXIT_SUCCESS File has been checked for readiness
101  * @ret #PXENV_EXIT_FAILURE File has not been checked for readiness
102  * @ret s_PXENV_FILE_SELECT::Status PXE status code
103  * @ret s_PXENV_FILE_SELECT::Ready Indication of readiness
104  *
105  */
106 static PXENV_EXIT_t
107 pxenv_file_select ( struct s_PXENV_FILE_SELECT *file_select ) {
108  fd_set fdset;
109  int ready;
110 
111  DBG ( "PXENV_FILE_SELECT %d", file_select->FileHandle );
112 
113  FD_ZERO ( &fdset );
114  FD_SET ( file_select->FileHandle, &fdset );
115  if ( ( ready = select ( &fdset, 0 ) ) < 0 ) {
116  file_select->Status = PXENV_STATUS ( ready );
117  return PXENV_EXIT_FAILURE;
118  }
119 
120  file_select->Ready = ( ready ? RDY_READ : 0 );
121  file_select->Status = PXENV_STATUS_SUCCESS;
122  return PXENV_EXIT_SUCCESS;
123 }
124 
125 /**
126  * FILE READ
127  *
128  * @v file_read Pointer to a struct s_PXENV_FILE_READ
129  * @v s_PXENV_FILE_READ::FileHandle File handle
130  * @v s_PXENV_FILE_READ::BufferSize Size of data buffer
131  * @v s_PXENV_FILE_READ::Buffer Data buffer
132  * @ret #PXENV_EXIT_SUCCESS Data has been read from file
133  * @ret #PXENV_EXIT_FAILURE Data has not been read from file
134  * @ret s_PXENV_FILE_READ::Status PXE status code
135  * @ret s_PXENV_FILE_READ::Ready Indication of readiness
136  * @ret s_PXENV_FILE_READ::BufferSize Length of data read
137  *
138  */
139 static PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ) {
140  void *buffer;
141  ssize_t len;
142 
143  DBG ( "PXENV_FILE_READ %d to %04x:%04x+%04x", file_read->FileHandle,
144  file_read->Buffer.segment, file_read->Buffer.offset,
145  file_read->BufferSize );
146 
147  buffer = real_to_virt ( file_read->Buffer.segment,
148  file_read->Buffer.offset );
149  if ( ( len = read ( file_read->FileHandle, buffer,
150  file_read->BufferSize ) ) < 0 ) {
151  file_read->Status = PXENV_STATUS ( len );
152  return PXENV_EXIT_FAILURE;
153  }
154 
155  DBG ( " read %04zx", ( ( size_t ) len ) );
156 
157  file_read->BufferSize = len;
158  file_read->Status = PXENV_STATUS_SUCCESS;
159  return PXENV_EXIT_SUCCESS;
160 }
161 
162 /**
163  * GET FILE SIZE
164  *
165  * @v get_file_size Pointer to a struct s_PXENV_GET_FILE_SIZE
166  * @v s_PXENV_GET_FILE_SIZE::FileHandle File handle
167  * @ret #PXENV_EXIT_SUCCESS File size has been determined
168  * @ret #PXENV_EXIT_FAILURE File size has not been determined
169  * @ret s_PXENV_GET_FILE_SIZE::Status PXE status code
170  * @ret s_PXENV_GET_FILE_SIZE::FileSize Size of file
171  */
172 static PXENV_EXIT_t
173 pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE *get_file_size ) {
174  ssize_t filesize;
175 
176  DBG ( "PXENV_GET_FILE_SIZE %d", get_file_size->FileHandle );
177 
178  filesize = fsize ( get_file_size->FileHandle );
179  if ( filesize < 0 ) {
180  get_file_size->Status = PXENV_STATUS ( filesize );
181  return PXENV_EXIT_FAILURE;
182  }
183 
184  DBG ( " is %zd", ( ( size_t ) filesize ) );
185 
186  get_file_size->FileSize = filesize;
187  get_file_size->Status = PXENV_STATUS_SUCCESS;
188  return PXENV_EXIT_SUCCESS;
189 }
190 
191 /**
192  * FILE EXEC
193  *
194  * @v file_exec Pointer to a struct s_PXENV_FILE_EXEC
195  * @v s_PXENV_FILE_EXEC::Command Command to execute
196  * @ret #PXENV_EXIT_SUCCESS Command was executed successfully
197  * @ret #PXENV_EXIT_FAILURE Command was not executed successfully
198  * @ret s_PXENV_FILE_EXEC::Status PXE status code
199  *
200  */
201 static PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) {
202  const char *command;
203  int rc;
204 
205  DBG ( "PXENV_FILE_EXEC" );
206 
207  /* Execute specified command */
208  command = real_to_virt ( file_exec->Command.segment,
209  file_exec->Command.offset );
210  DBG ( " %s", command );
211  if ( ( rc = system ( command ) ) != 0 ) {
212  file_exec->Status = PXENV_STATUS ( rc );
213  return PXENV_EXIT_FAILURE;
214  }
215 
216  file_exec->Status = PXENV_STATUS_SUCCESS;
217  return PXENV_EXIT_SUCCESS;
218 }
219 
220 /**
221  * FILE CMDLINE
222  *
223  * @v file_cmdline Pointer to a struct s_PXENV_FILE_CMDLINE
224  * @v s_PXENV_FILE_CMDLINE::Buffer Buffer to contain command line
225  * @v s_PXENV_FILE_CMDLINE::BufferSize Size of buffer
226  * @ret #PXENV_EXIT_SUCCESS Command was executed successfully
227  * @ret #PXENV_EXIT_FAILURE Command was not executed successfully
228  * @ret s_PXENV_FILE_EXEC::Status PXE status code
229  * @ret s_PXENV_FILE_EXEC::BufferSize Length of command line (including NUL)
230  *
231  */
232 static PXENV_EXIT_t
233 pxenv_file_cmdline ( struct s_PXENV_FILE_CMDLINE *file_cmdline ) {
234  char *buffer;
235  size_t len;
236 
237  DBG ( "PXENV_FILE_CMDLINE to %04x:%04x+%04x \"%s\"\n",
238  file_cmdline->Buffer.segment, file_cmdline->Buffer.offset,
239  file_cmdline->BufferSize, pxe_cmdline );
240 
241  buffer = real_to_virt ( file_cmdline->Buffer.segment,
242  file_cmdline->Buffer.offset );
243  len = file_cmdline->BufferSize;
244  if ( pxe_cmdline ) {
245  len = snprintf ( buffer, len, "%s", pxe_cmdline );
246  file_cmdline->BufferSize = ( len + 1 /* NUL */ );
247  } else {
248  file_cmdline->BufferSize = 0;
249  }
250 
251  file_cmdline->Status = PXENV_STATUS_SUCCESS;
252  return PXENV_EXIT_SUCCESS;
253 }
254 
255 /**
256  * FILE API CHECK
257  *
258  * @v file_exec Pointer to a struct s_PXENV_FILE_API_CHECK
259  * @v s_PXENV_FILE_API_CHECK::Magic Inbound magic number (0x91d447b2)
260  * @ret #PXENV_EXIT_SUCCESS Command was executed successfully
261  * @ret #PXENV_EXIT_FAILURE Command was not executed successfully
262  * @ret s_PXENV_FILE_API_CHECK::Status PXE status code
263  * @ret s_PXENV_FILE_API_CHECK::Magic Outbound magic number (0xe9c17b20)
264  * @ret s_PXENV_FILE_API_CHECK::Provider "iPXE" (0x45585067)
265  * @ret s_PXENV_FILE_API_CHECK::APIMask API function bitmask
266  * @ret s_PXENV_FILE_API_CHECK::Flags Reserved
267  *
268  */
269 static PXENV_EXIT_t
270 pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_check ) {
271  struct pxe_api_call *call;
272  unsigned int mask = 0;
273  unsigned int offset;
274 
275  DBG ( "PXENV_FILE_API_CHECK" );
276 
277  /* Check for magic value */
278  if ( file_api_check->Magic != 0x91d447b2 ) {
279  file_api_check->Status = PXENV_STATUS_BAD_FUNC;
280  return PXENV_EXIT_FAILURE;
281  }
282 
283  /* Check for required parameter size */
284  if ( file_api_check->Size < sizeof ( *file_api_check ) ) {
285  file_api_check->Status = PXENV_STATUS_OUT_OF_RESOURCES;
286  return PXENV_EXIT_FAILURE;
287  }
288 
289  /* Determine supported calls */
291  offset = ( call->opcode - PXENV_FILE_MIN );
292  if ( offset <= ( PXENV_FILE_MAX - PXENV_FILE_MIN ) )
293  mask |= ( 1 << offset );
294  }
295 
296  /* Fill in parameters */
297  file_api_check->Size = sizeof ( *file_api_check );
298  file_api_check->Magic = 0xe9c17b20;
299  file_api_check->Provider = 0x45585067; /* "iPXE" */
300  file_api_check->APIMask = mask;
301  file_api_check->Flags = 0; /* None defined */
302 
303  file_api_check->Status = PXENV_STATUS_SUCCESS;
304  return PXENV_EXIT_SUCCESS;
305 }
306 
307 /** PXE file API */
308 struct pxe_api_call pxe_file_api[] __pxe_api_call = {
310  struct s_PXENV_FILE_OPEN ),
312  struct s_PXENV_FILE_CLOSE ),
314  struct s_PXENV_FILE_SELECT ),
316  struct s_PXENV_FILE_READ ),
318  struct s_PXENV_GET_FILE_SIZE ),
320  struct s_PXENV_FILE_EXEC ),
322  struct s_PXENV_FILE_CMDLINE ),
324  struct s_PXENV_FILE_API_CHECK ),
325 };
#define PXENV_FILE_CMDLINE
PXE API function code for pxenv_file_cmdline()
Definition: pxe_api.h:1706
#define PXENV_STATUS_OUT_OF_RESOURCES
Definition: pxe_error.h:25
UINT16_t FileHandle
File handle.
Definition: pxe_api.h:1604
struct option_descriptor read[1]
Definition: nvo_cmd.c:115
#define PXENV_FILE_SELECT
PXE API function code for pxenv_file_select()
Definition: pxe_api.h:1575
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define RDY_READ
File is ready for reading.
Definition: pxe_api.h:1578
#define PXENV_EXIT_FAILURE
An error occurred.
Definition: pxe_types.h:46
UINT32_t Provider
Implementation identifier.
Definition: pxe_api.h:1669
SEGOFF16_t Buffer
Data buffer.
Definition: pxe_api.h:1712
UINT16_t BufferSize
Data buffer size.
Definition: pxe_api.h:1711
UINT16_t FileHandle
File handle.
Definition: pxe_api.h:1626
#define DHCP_EB_FEATURE_PXE_EXT
PXE API extensions.
Definition: features.h:36
#define PXENV_FILE_READ
PXE API function code for pxenv_file_read()
Definition: pxe_api.h:1599
static PXENV_EXIT_t pxenv_file_api_check(struct s_PXENV_FILE_API_CHECK *file_api_check)
FILE API CHECK.
Definition: pxe_file.c:270
Error codes.
static PXENV_EXIT_t pxenv_file_open(struct s_PXENV_FILE_OPEN *file_open)
FILE OPEN.
Definition: pxe_file.c:54
static PXENV_EXIT_t pxenv_file_select(struct s_PXENV_FILE_SELECT *file_select)
FILE SELECT.
Definition: pxe_file.c:107
A command-line command.
Definition: command.h:9
#define PXENV_FILE_CLOSE
PXE API function code for pxenv_file_close()
Definition: pxe_api.h:1555
Parameter block for pxenv_file_close()
Definition: pxe_api.h:1558
#define PXENV_GET_FILE_SIZE
PXE API function code for pxenv_get_file_size()
Definition: pxe_api.h:1621
#define PXENV_STATUS_BAD_FUNC
Definition: pxe_error.h:21
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1710
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
#define PXENV_FILE_API_CHECK
PXE API function code for pxenv_file_api_check()
Definition: pxe_api.h:1662
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1666
UINT16_t FileHandle
File handle.
Definition: pxe_api.h:1560
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1582
static __always_inline void * real_to_virt(unsigned int segment, unsigned int offset)
Convert segment:offset address to virtual address.
Definition: realmode.h:77
#define PXE_API_CALL(_opcode, _entry, _params_type)
Define a PXE API call.
Definition: pxe.h:106
Parameter block for pxenv_file_api_check()
Definition: pxe_api.h:1665
static PXENV_EXIT_t pxenv_file_close(struct s_PXENV_FILE_CLOSE *file_close)
FILE CLOSE.
Definition: pxe_file.c:86
ssize_t fsize(int fd)
Determine file size.
Definition: posix_io.c:310
Parameter block for pxenv_file_select()
Definition: pxe_api.h:1581
UINT16_t PXENV_EXIT_t
A PXE exit code.
Definition: pxe_types.h:44
UINT32_t Flags
Reserved for the future.
Definition: pxe_api.h:1671
#define PXENV_FILE_EXEC
PXE API function code for pxenv_file_exec()
Definition: pxe_api.h:1642
ring len
Length.
Definition: dwmac.h:231
#define PXE_API_CALLS
PXE API call table.
Definition: pxe.h:93
struct pxe_api_call pxe_file_api [] __pxe_api_call
PXE file API.
Definition: pxe_file.c:308
const char * pxe_cmdline
PXE command line.
Definition: pxe_image.c:48
Parameter block for pxenv_get_file_size()
Definition: pxe_api.h:1624
UINT16_t Ready
Indication of readiness.
Definition: pxe_api.h:1584
Parameter block for pxenv_file_exec()
Definition: pxe_api.h:1645
Feature list.
SEGOFF16_t FileName
File URL.
Definition: pxe_api.h:1539
UINT16_t FileHandle
File handle.
Definition: pxe_api.h:1583
UINT32_t Magic
Magic number.
Definition: pxe_api.h:1668
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1625
uint32_t fd_set
File descriptor set as used for select()
Definition: posix_io.h:21
#define FEATURE_MISC
Miscellaneous.
Definition: features.h:23
SEGOFF16_t Command
Command to execute.
Definition: pxe_api.h:1647
FEATURE(FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 2)
static PXENV_EXIT_t pxenv_file_exec(struct s_PXENV_FILE_EXEC *file_exec)
FILE EXEC.
Definition: pxe_file.c:201
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:385
int select(fd_set *readfds, int wait)
Check file descriptors for readiness.
Definition: posix_io.c:229
Parameter block for pxenv_file_cmdline()
Definition: pxe_api.h:1709
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static int command
Definition: epic100.c:68
uint16_t opcode
Opcode.
Definition: pxe.h:89
#define PXENV_EXIT_SUCCESS
No error occurred.
Definition: pxe_types.h:45
UINT32_t APIMask
Supported API functions.
Definition: pxe_api.h:1670
static PXENV_EXIT_t pxenv_file_read(struct s_PXENV_FILE_READ *file_read)
FILE READ.
Definition: pxe_file.c:139
SEGOFF16_t Buffer
Data buffer.
Definition: pxe_api.h:1606
Parameter block for pxenv_file_open()
Definition: pxe_api.h:1536
A PXE API call.
Definition: pxe.h:81
UINT16_t FileHandle
File handle.
Definition: pxe_api.h:1538
UINT16_t Size
Size of structure.
Definition: pxe_api.h:1667
#define PXENV_FILE_MAX
Minimum possible opcode used within PXE FILE API.
Definition: pxe_api.h:1523
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1537
#define PXENV_FILE_OPEN
PXE API function code for pxenv_file_open()
Definition: pxe_api.h:1533
UINT32_t FileSize
File size.
Definition: pxe_api.h:1627
#define PXENV_FILE_MIN
Minimum possible opcode used within PXE FILE API.
Definition: pxe_api.h:1520
int open(const char *uri_string)
Open file.
Definition: posix_io.c:176
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1559
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1646
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
Parameter block for pxenv_file_read()
Definition: pxe_api.h:1602
signed long ssize_t
Definition: stdint.h:7
static struct evtchn_close * close
Definition: xenevent.h:23
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1603
#define PXENV_STATUS_SUCCESS
Definition: pxe_error.h:19
POSIX-like I/O.
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static PXENV_EXIT_t pxenv_get_file_size(struct s_PXENV_GET_FILE_SIZE *get_file_size)
GET FILE SIZE.
Definition: pxe_file.c:173
#define PXENV_STATUS(rc)
Derive PXENV_STATUS code from iPXE error number.
Definition: pxe_error.h:121
uint8_t system[ETH_ALEN]
System identifier.
Definition: eth_slow.h:24
static PXENV_EXIT_t pxenv_file_cmdline(struct s_PXENV_FILE_CMDLINE *file_cmdline)
FILE CMDLINE.
Definition: pxe_file.c:233
UINT16_t BufferSize
Data buffer size.
Definition: pxe_api.h:1605