Sfoglia il codice sorgente

Merge branch 'master' of git://git.etherboot.org/scm/gpxe

tags/v0.9.3
Holger Lubitz 17 anni fa
parent
commit
b79d438080

+ 25
- 0
src/arch/i386/interface/pxe/pxe_call.c Vedi File

@@ -91,6 +91,11 @@ union pxenv_call {
91 91
 			( struct s_PXENV_UNDI_GET_IFACE_INFO * );
92 92
 	PXENV_EXIT_t ( * undi_get_state ) ( struct s_PXENV_UNDI_GET_STATE * );
93 93
 	PXENV_EXIT_t ( * undi_isr ) ( struct s_PXENV_UNDI_ISR * );
94
+	PXENV_EXIT_t ( * file_open ) ( struct s_PXENV_FILE_OPEN * );
95
+	PXENV_EXIT_t ( * file_close ) ( struct s_PXENV_FILE_CLOSE * );
96
+	PXENV_EXIT_t ( * file_select ) ( struct s_PXENV_FILE_SELECT * );
97
+	PXENV_EXIT_t ( * file_read ) ( struct s_PXENV_FILE_READ * );
98
+	PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * );
94 99
 };
95 100
 
96 101
 /**
@@ -269,6 +274,26 @@ __cdecl void pxe_api_call ( struct i386_all_regs *ix86 ) {
269 274
 		pxenv_call.undi_isr = pxenv_undi_isr;
270 275
 		param_len = sizeof ( pxenv_any.undi_isr );
271 276
 		break;
277
+	case PXENV_FILE_OPEN:
278
+		pxenv_call.file_open = pxenv_file_open;
279
+		param_len = sizeof ( pxenv_any.file_open );
280
+		break;
281
+	case PXENV_FILE_CLOSE:
282
+		pxenv_call.file_close = pxenv_file_close;
283
+		param_len = sizeof ( pxenv_any.file_close );
284
+		break;
285
+	case PXENV_FILE_SELECT:
286
+		pxenv_call.file_select = pxenv_file_select;
287
+		param_len = sizeof ( pxenv_any.file_select );
288
+		break;
289
+	case PXENV_FILE_READ:
290
+		pxenv_call.file_read = pxenv_file_read;
291
+		param_len = sizeof ( pxenv_any.file_read );
292
+		break;
293
+	case PXENV_GET_FILE_SIZE:
294
+		pxenv_call.get_file_size = pxenv_get_file_size;
295
+		param_len = sizeof ( pxenv_any.get_file_size );
296
+		break;
272 297
 	default:
273 298
 		DBG ( "PXENV_UNKNOWN_%hx", opcode );
274 299
 		pxenv_call.unknown = pxenv_unknown;

+ 12
- 3
src/core/image.c Vedi File

@@ -237,6 +237,7 @@ int image_autoload ( struct image *image ) {
237 237
  * @ret rc		Return status code
238 238
  */
239 239
 int image_exec ( struct image *image ) {
240
+	struct uri *old_cwuri;
240 241
 	int rc;
241 242
 
242 243
 	/* Image must be loaded first */
@@ -252,15 +253,23 @@ int image_exec ( struct image *image ) {
252 253
 	if ( ! image->type->exec )
253 254
 		return -ENOEXEC;
254 255
 
256
+	/* Switch current working directory to be that of the image itself */
257
+	old_cwuri = uri_get ( cwuri );
258
+	churi ( image->uri );
259
+
255 260
 	/* Try executing the image */
256 261
 	if ( ( rc = image->type->exec ( image ) ) != 0 ) {
257 262
 		DBGC ( image, "IMAGE %p could not execute: %s\n",
258 263
 		       image, strerror ( rc ) );
259
-		return rc;
264
+		goto done;
260 265
 	}
261 266
 
262
-	/* Well, some formats might return... */
263
-	return 0;
267
+ done:
268
+	/* Reset current working directory */
269
+	churi ( old_cwuri );
270
+	uri_put ( old_cwuri );
271
+
272
+	return rc;
264 273
 }
265 274
 
266 275
 /**

+ 59
- 35
src/core/posix_io.c Vedi File

@@ -60,12 +60,6 @@ struct posix_file {
60 60
 /** List of open files */
61 61
 static LIST_HEAD ( posix_files );
62 62
 
63
-/** Minimum file descriptor that will ever be allocated */
64
-#define POSIX_FD_MIN ( 1 )
65
-
66
-/** Maximum file descriptor that will ever be allocated */
67
-#define POSIX_FD_MAX ( 255 )
68
-
69 63
 /**
70 64
  * Free open file
71 65
  *
@@ -251,6 +245,38 @@ int open ( const char *uri_string ) {
251 245
 	return rc;
252 246
 }
253 247
 
248
+/**
249
+ * Check file descriptors for readiness
250
+ *
251
+ * @v readfds		File descriptors to check
252
+ * @v wait		Wait until data is ready
253
+ * @ret nready		Number of ready file descriptors
254
+ */
255
+int select ( fd_set *readfds, int wait ) {
256
+	struct posix_file *file;
257
+	int fd;
258
+
259
+	do {
260
+		for ( fd = POSIX_FD_MIN ; fd <= POSIX_FD_MAX ; fd++ ) {
261
+			if ( ! FD_ISSET ( fd, readfds ) )
262
+				continue;
263
+			file = posix_fd_to_file ( fd );
264
+			if ( ! file )
265
+				return -EBADF;
266
+			if ( ( list_empty ( &file->data ) ) &&
267
+			     ( file->rc != -EINPROGRESS ) )
268
+				continue;
269
+			/* Data is available or status has changed */
270
+			FD_ZERO ( readfds );
271
+			FD_SET ( fd, readfds );
272
+			return 1;
273
+		}
274
+		step();
275
+	} while ( wait );
276
+
277
+	return 0;
278
+}
279
+
254 280
 /**
255 281
  * Read data from file
256 282
  *
@@ -258,47 +284,45 @@ int open ( const char *uri_string ) {
258 284
  * @v offset		Starting offset within data buffer
259 285
  * @v len		Maximum length to read
260 286
  * @ret len		Actual length read, or negative error number
287
+ *
288
+ * This call is non-blocking; if no data is available to read then
289
+ * -EWOULDBLOCK will be returned.
261 290
  */
262 291
 ssize_t read_user ( int fd, userptr_t buffer, off_t offset, size_t max_len ) {
263 292
 	struct posix_file *file;
264 293
 	struct io_buffer *iobuf;
265
-	size_t frag_len;
266
-	ssize_t len = 0;
294
+	size_t len;
267 295
 
268 296
 	/* Identify file */
269 297
 	file = posix_fd_to_file ( fd );
270 298
 	if ( ! file )
271 299
 		return -EBADF;
272 300
 
273
-	while ( 1 ) {
274
-		/* Try to fetch more data if none available */
275
-		if ( list_empty ( &file->data ) )
276
-			step();
277
-		/* Dequeue at most one received I/O buffer into user buffer */
278
-		list_for_each_entry ( iobuf, &file->data, list ) {
279
-			frag_len = iob_len ( iobuf );
280
-			if ( frag_len > max_len )
281
-				frag_len = max_len;
282
-			copy_to_user ( buffer, offset, iobuf->data,
283
-				       frag_len );
284
-			iob_pull ( iobuf, frag_len );
285
-			if ( ! iob_len ( iobuf ) ) {
286
-				list_del ( &iobuf-> list );
287
-				free_iob ( iobuf );
288
-			}
289
-			file->pos += frag_len;
290
-			len += frag_len;
291
-			offset += frag_len;
292
-			max_len -= frag_len;
293
-			break;
301
+	/* Try to fetch more data if none available */
302
+	if ( list_empty ( &file->data ) )
303
+		step();
304
+
305
+	/* Dequeue at most one received I/O buffer into user buffer */
306
+	list_for_each_entry ( iobuf, &file->data, list ) {
307
+		len = iob_len ( iobuf );
308
+		if ( len > max_len )
309
+			len = max_len;
310
+		copy_to_user ( buffer, offset, iobuf->data, len );
311
+		iob_pull ( iobuf, len );
312
+		if ( ! iob_len ( iobuf ) ) {
313
+			list_del ( &iobuf->list );
314
+			free_iob ( iobuf );
294 315
 		}
295
-		/* If buffer is full, return */
296
-		if ( ! max_len )
297
-			return len;
298
-		/* If file has completed, return */
299
-		if ( file->rc != -EINPROGRESS )
300
-			return ( file->rc ? file->rc : len );
316
+		file->pos += len;
317
+		return len;
301 318
 	}
319
+
320
+	/* If file has completed, return (after returning all data) */
321
+	if ( file->rc != -EINPROGRESS )
322
+		return file->rc;
323
+
324
+	/* No data ready and file still in progress; return -WOULDBLOCK */
325
+	return -EWOULDBLOCK;
302 326
 }
303 327
 
304 328
 /**

+ 1
- 9
src/image/script.c Vedi File

@@ -27,7 +27,6 @@
27 27
 #include <stdlib.h>
28 28
 #include <errno.h>
29 29
 #include <gpxe/image.h>
30
-#include <gpxe/uri.h>
31 30
 
32 31
 struct image_type script_image_type __image_type ( PROBE_NORMAL );
33 32
 
@@ -38,7 +37,6 @@ struct image_type script_image_type __image_type ( PROBE_NORMAL );
38 37
  * @ret rc		Return status code
39 38
  */
40 39
 static int script_exec ( struct image *image ) {
41
-	struct uri *old_cwuri;
42 40
 	char cmdbuf[256];
43 41
 	size_t offset = 0;
44 42
 	size_t remaining;
@@ -53,10 +51,6 @@ static int script_exec ( struct image *image ) {
53 51
 	image_get ( image );
54 52
 	unregister_image ( image );
55 53
 
56
-	/* Switch current working directory to be that of the script itself */
57
-	old_cwuri = uri_get ( cwuri );
58
-	churi ( image->uri );
59
-
60 54
 	while ( offset < image->len ) {
61 55
 	
62 56
 		/* Read up to cmdbuf bytes from script into buffer */
@@ -93,9 +87,7 @@ static int script_exec ( struct image *image ) {
93 87
 
94 88
 	rc = 0;
95 89
  done:
96
-	/* Reset current working directory, re-register image and return */
97
-	churi ( old_cwuri );
98
-	uri_put ( old_cwuri );
90
+	/* Re-register image and return */
99 91
 	register_image ( image );
100 92
 	image_put ( image );
101 93
 	return rc;

+ 54
- 0
src/include/gpxe/posix_io.h Vedi File

@@ -10,12 +10,66 @@
10 10
 #include <stdint.h>
11 11
 #include <gpxe/uaccess.h>
12 12
 
13
+/** Minimum file descriptor that will ever be allocated */
14
+#define POSIX_FD_MIN ( 1 )
15
+
16
+/** Maximum file descriptor that will ever be allocated */
17
+#define POSIX_FD_MAX ( 31 )
18
+
19
+/** File descriptor set as used for select() */
20
+typedef uint32_t fd_set;
21
+
13 22
 extern int open ( const char *uri_string );
14 23
 extern ssize_t read_user ( int fd, userptr_t buffer,
15 24
 			   off_t offset, size_t len );
25
+extern int select ( fd_set *readfds, int wait );
16 26
 extern ssize_t fsize ( int fd );
17 27
 extern int close ( int fd );
18 28
 
29
+/**
30
+ * Zero a file descriptor set
31
+ *
32
+ * @v set		File descriptor set
33
+ */
34
+static inline __attribute__ (( always_inline )) void
35
+FD_ZERO ( fd_set *set ) {
36
+	*set = 0;
37
+}
38
+
39
+/**
40
+ * Set a bit within a file descriptor set
41
+ *
42
+ * @v fd		File descriptor
43
+ * @v set		File descriptor set
44
+ */
45
+static inline __attribute__ (( always_inline )) void
46
+FD_SET ( int fd, fd_set *set ) {
47
+	*set |= ( 1 << fd );
48
+}
49
+
50
+/**
51
+ * Clear a bit within a file descriptor set
52
+ *
53
+ * @v fd		File descriptor
54
+ * @v set		File descriptor set
55
+ */
56
+static inline __attribute__ (( always_inline )) void
57
+FD_CLR ( int fd, fd_set *set ) {
58
+	*set &= ~( 1 << fd );
59
+}
60
+
61
+/**
62
+ * Test a bit within a file descriptor set
63
+ *
64
+ * @v fd		File descriptor
65
+ * @v set		File descriptor set
66
+ * @ret is_set		Corresponding bit is set
67
+ */
68
+static inline __attribute__ (( always_inline )) int
69
+FD_ISSET ( int fd, fd_set *set ) {
70
+	return ( *set & ( 1 << fd ) );
71
+}
72
+
19 73
 /**
20 74
  * Read data from file
21 75
  *

+ 5
- 0
src/include/pxe.h Vedi File

@@ -58,6 +58,11 @@ union u_PXENV_ANY {
58 58
 	struct s_PXENV_UNDI_GET_IFACE_INFO	undi_get_iface_info;
59 59
 	struct s_PXENV_UNDI_GET_STATE		undi_get_state;
60 60
 	struct s_PXENV_UNDI_ISR			undi_isr;
61
+	struct s_PXENV_FILE_OPEN		file_open;
62
+	struct s_PXENV_FILE_CLOSE		file_close;
63
+	struct s_PXENV_FILE_SELECT		file_select;
64
+	struct s_PXENV_FILE_READ		file_read;
65
+	struct s_PXENV_GET_FILE_SIZE		get_file_size;
61 66
 };
62 67
 
63 68
 typedef union u_PXENV_ANY PXENV_ANY_t;

+ 131
- 0
src/include/pxe_api.h Vedi File

@@ -1555,6 +1555,137 @@ extern PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr );
1555 1555
 
1556 1556
 /** @} */ /* pxe_undi_api */
1557 1557
 
1558
+/** @defgroup pxe_file_api PXE FILE API
1559
+ *
1560
+ * POSIX-like file operations
1561
+ *
1562
+ * @{
1563
+ */
1564
+
1565
+/** @defgroup pxenv_file_open PXENV_FILE_OPEN
1566
+ *
1567
+ * FILE OPEN
1568
+ *
1569
+ * @{
1570
+ */
1571
+
1572
+/** PXE API function code for pxenv_file_open() */
1573
+#define PXENV_FILE_OPEN			0x00e0
1574
+
1575
+/** Parameter block for pxenv_file_open() */
1576
+struct s_PXENV_FILE_OPEN {
1577
+	PXENV_STATUS_t Status;		/**< PXE status code */
1578
+	UINT16_t FileHandle;		/**< File handle */
1579
+	SEGOFF16_t FileName;		/**< File URL */
1580
+	UINT32_t Reserved;		/**< Reserved */
1581
+} PACKED;
1582
+
1583
+typedef struct s_PXENV_FILE_OPEN PXENV_FILE_OPEN_t;
1584
+
1585
+extern PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open );
1586
+
1587
+/** @} */ /* pxenv_file_open */
1588
+
1589
+/** @defgroup pxenv_file_close PXENV_FILE_CLOSE
1590
+ *
1591
+ * FILE CLOSE
1592
+ *
1593
+ * @{
1594
+ */
1595
+
1596
+/** PXE API function code for pxenv_file_close() */
1597
+#define PXENV_FILE_CLOSE		0x00e1
1598
+
1599
+/** Parameter block for pxenv_file_close() */
1600
+struct s_PXENV_FILE_CLOSE {
1601
+	PXENV_STATUS_t Status;		/**< PXE status code */
1602
+	UINT16_t FileHandle;		/**< File handle */
1603
+} PACKED;
1604
+
1605
+typedef struct s_PXENV_FILE_CLOSE PXENV_FILE_CLOSE_t;
1606
+
1607
+extern PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE
1608
+				       *file_close );
1609
+
1610
+/** @} */ /* pxenv_file_close */
1611
+
1612
+/** @defgroup pxenv_file_select PXENV_FILE_SELECT
1613
+ *
1614
+ * FILE SELECT
1615
+ *
1616
+ * @{
1617
+ */
1618
+
1619
+/** PXE API function code for pxenv_file_select() */
1620
+#define PXENV_FILE_SELECT		0x00e2
1621
+
1622
+/** File is ready for reading */
1623
+#define RDY_READ			0x0001
1624
+
1625
+/** Parameter block for pxenv_file_select() */
1626
+struct s_PXENV_FILE_SELECT {
1627
+	PXENV_STATUS_t Status;		/**< PXE status code */
1628
+	UINT16_t FileHandle;		/**< File handle */
1629
+	UINT16_t Ready;			/**< Indication of readiness */
1630
+} PACKED;
1631
+
1632
+typedef struct s_PXENV_FILE_SELECT PXENV_FILE_SELECT_t;
1633
+
1634
+extern PXENV_EXIT_t pxenv_file_select ( struct s_PXENV_FILE_SELECT
1635
+					*file_select );
1636
+
1637
+/** @} */ /* pxenv_file_select */
1638
+
1639
+/** @defgroup pxenv_file_read PXENV_FILE_READ
1640
+ *
1641
+ * FILE READ
1642
+ *
1643
+ * @{
1644
+ */
1645
+
1646
+/** PXE API function code for pxenv_file_read() */
1647
+#define PXENV_FILE_READ		0x00e3
1648
+
1649
+/** Parameter block for pxenv_file_read() */
1650
+struct s_PXENV_FILE_READ {
1651
+	PXENV_STATUS_t Status;		/**< PXE status code */
1652
+	UINT16_t FileHandle;		/**< File handle */
1653
+	UINT16_t BufferSize;		/**< Data buffer size */
1654
+	SEGOFF16_t Buffer;		/**< Data buffer */
1655
+} PACKED;
1656
+
1657
+typedef struct s_PXENV_FILE_READ PXENV_FILE_READ_t;
1658
+
1659
+extern PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read );
1660
+
1661
+/** @} */ /* pxenv_file_read */
1662
+
1663
+/** @defgroup pxenv_get_file_size PXENV_GET_FILE_SIZE
1664
+ *
1665
+ * GET FILE SIZE
1666
+ *
1667
+ * @{
1668
+ */
1669
+
1670
+/** PXE API function code for pxenv_get_file_size() */
1671
+#define PXENV_GET_FILE_SIZE		0x00e4
1672
+
1673
+/** Parameter block for pxenv_get_file_size() */
1674
+struct s_PXENV_GET_FILE_SIZE {
1675
+	PXENV_STATUS_t Status;		/**< PXE status code */
1676
+	UINT16_t FileHandle;		/**< File handle */
1677
+	UINT32_t FileSize;		/**< File size */
1678
+} PACKED;
1679
+
1680
+typedef struct s_PXENV_GET_FILE_SIZE PXENV_GET_FILE_SIZE_t;
1681
+
1682
+extern PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE
1683
+					  *get_file_size );
1684
+
1685
+/** @} */ /* pxenv_get_file_size */
1686
+
1687
+/** @} */ /* pxe_file_api */
1688
+
1558 1689
 /** @defgroup pxe_loader_api PXE Loader API
1559 1690
  *
1560 1691
  * The UNDI ROM loader API

+ 191
- 0
src/interface/pxe/pxe_file.c Vedi File

@@ -0,0 +1,191 @@
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 <gpxe/uaccess.h>
12
+#include <gpxe/posix_io.h>
13
+#include <gpxe/features.h>
14
+#include <pxe.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., 675 Mass Ave, Cambridge, MA 02139, USA.
32
+ */
33
+
34
+FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 1 );
35
+
36
+/**
37
+ * FILE OPEN
38
+ *
39
+ * @v file_open				Pointer to a struct s_PXENV_FILE_OPEN
40
+ * @v s_PXENV_FILE_OPEN::FileName	URL of file to open
41
+ * @ret #PXENV_EXIT_SUCCESS		File was opened
42
+ * @ret #PXENV_EXIT_FAILURE		File was not opened
43
+ * @ret s_PXENV_FILE_OPEN::Status	PXE status code
44
+ * @ret s_PXENV_FILE_OPEN::FileHandle	Handle of opened file
45
+ *
46
+ */
47
+PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ) {
48
+	userptr_t filename;
49
+	size_t filename_len;
50
+	int fd;
51
+
52
+	DBG ( "PXENV_FILE_OPEN" );
53
+
54
+	/* Copy name from external program, and open it */
55
+	filename = real_to_user ( file_open->FileName.segment,
56
+			      file_open->FileName.offset );
57
+	filename_len = strlen_user ( filename, 0 );
58
+	{
59
+		char uri_string[ filename_len + 1 ];
60
+
61
+		copy_from_user ( uri_string, filename, 0,
62
+				 sizeof ( uri_string ) );
63
+		DBG ( " %s", uri_string );
64
+		fd = open ( uri_string );
65
+	}
66
+
67
+	if ( fd < 0 ) {
68
+		file_open->Status = PXENV_STATUS ( fd );
69
+		return PXENV_EXIT_FAILURE;
70
+	}
71
+
72
+	DBG ( " as file %d", fd );
73
+
74
+	file_open->FileHandle = fd;
75
+	file_open->Status = PXENV_STATUS_SUCCESS;
76
+	return PXENV_EXIT_SUCCESS;
77
+}
78
+
79
+/**
80
+ * FILE CLOSE
81
+ *
82
+ * @v file_close			Pointer to a struct s_PXENV_FILE_CLOSE
83
+ * @v s_PXENV_FILE_CLOSE::FileHandle	File handle
84
+ * @ret #PXENV_EXIT_SUCCESS		File was closed
85
+ * @ret #PXENV_EXIT_FAILURE		File was not closed
86
+ * @ret s_PXENV_FILE_CLOSE::Status	PXE status code
87
+ *
88
+ */
89
+PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE *file_close ) {
90
+
91
+	DBG ( "PXENV_FILE_CLOSE %d", file_close->FileHandle );
92
+
93
+	close ( file_close->FileHandle );
94
+	file_close->Status = PXENV_STATUS_SUCCESS;
95
+	return PXENV_EXIT_SUCCESS;
96
+}
97
+
98
+/**
99
+ * FILE SELECT
100
+ *
101
+ * @v file_select			Pointer to a struct s_PXENV_FILE_SELECT
102
+ * @v s_PXENV_FILE_SELECT::FileHandle	File handle
103
+ * @ret #PXENV_EXIT_SUCCESS		File has been checked for readiness
104
+ * @ret #PXENV_EXIT_FAILURE		File has not been checked for readiness
105
+ * @ret s_PXENV_FILE_SELECT::Status	PXE status code
106
+ * @ret s_PXENV_FILE_SELECT::Ready	Indication of readiness
107
+ *
108
+ */
109
+PXENV_EXIT_t pxenv_file_select ( struct s_PXENV_FILE_SELECT *file_select ) {
110
+	fd_set fdset;
111
+	int ready;
112
+
113
+	DBG ( "PXENV_FILE_SELECT %d", file_select->FileHandle );
114
+
115
+	FD_ZERO ( &fdset );
116
+	FD_SET ( file_select->FileHandle, &fdset );
117
+	if ( ( ready = select ( &fdset, 0 ) ) < 0 ) {
118
+		file_select->Status = PXENV_STATUS ( ready );
119
+		return PXENV_EXIT_FAILURE;
120
+	}
121
+
122
+	file_select->Ready = ( ready ? RDY_READ : 0 );
123
+	file_select->Status = PXENV_STATUS_SUCCESS;
124
+	return PXENV_EXIT_SUCCESS;
125
+}
126
+
127
+/**
128
+ * FILE READ
129
+ *
130
+ * @v file_read				Pointer to a struct s_PXENV_FILE_READ
131
+ * @v s_PXENV_FILE_READ::FileHandle	File handle
132
+ * @v s_PXENV_FILE_READ::BufferSize	Size of data buffer
133
+ * @v s_PXENV_FILE_READ::Buffer		Data buffer
134
+ * @ret #PXENV_EXIT_SUCCESS		Data has been read from file
135
+ * @ret #PXENV_EXIT_FAILURE		Data has not been read from file
136
+ * @ret s_PXENV_FILE_READ::Status	PXE status code
137
+ * @ret s_PXENV_FILE_READ::Ready	Indication of readiness
138
+ * @ret s_PXENV_FILE_READ::BufferSize	Length of data read
139
+ *
140
+ */
141
+PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ) {
142
+	userptr_t buffer;
143
+	ssize_t len;
144
+
145
+	DBG ( "PXENV_FILE_READ %d to %04x:%04x+%04x", file_read->FileHandle,
146
+	      file_read->Buffer.segment, file_read->Buffer.offset,
147
+	      file_read->BufferSize );
148
+
149
+	buffer = real_to_user ( file_read->Buffer.segment,
150
+				file_read->Buffer.offset );
151
+	if ( ( len = read_user ( file_read->FileHandle, buffer, 0,
152
+				file_read->BufferSize ) ) < 0 ) {
153
+		file_read->Status = PXENV_STATUS ( len );
154
+		return PXENV_EXIT_FAILURE;
155
+	}
156
+
157
+	DBG ( " read %04zx", ( ( size_t ) len ) );
158
+
159
+	file_read->BufferSize = len;
160
+	file_read->Status = PXENV_STATUS_SUCCESS;
161
+	return PXENV_EXIT_SUCCESS;
162
+}
163
+
164
+/**
165
+ * GET FILE SIZE
166
+ *
167
+ * @v get_file_size			Pointer to a struct s_PXENV_GET_FILE_SIZE
168
+ * @v s_PXENV_GET_FILE_SIZE::FileHandle	File handle
169
+ * @ret #PXENV_EXIT_SUCCESS		File size has been determined
170
+ * @ret #PXENV_EXIT_FAILURE		File size has not been determined
171
+ * @ret s_PXENV_GET_FILE_SIZE::Status	PXE status code
172
+ * @ret s_PXENV_GET_FILE_SIZE::FileSize	Size of file
173
+ */
174
+PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE
175
+				   *get_file_size ) {
176
+	ssize_t filesize;
177
+
178
+	DBG ( "PXENV_GET_FILE_SIZE %d", get_file_size->FileHandle );
179
+
180
+	filesize = fsize ( get_file_size->FileHandle );
181
+	if ( filesize < 0 ) {
182
+		get_file_size->Status = PXENV_STATUS ( filesize );
183
+		return PXENV_EXIT_FAILURE;
184
+	}
185
+
186
+	DBG ( " is %zd", ( ( size_t ) filesize ) );
187
+
188
+	get_file_size->FileSize = filesize;
189
+	get_file_size->Status = PXENV_STATUS_SUCCESS;
190
+	return PXENV_EXIT_SUCCESS;
191
+}

+ 38
- 15
src/interface/pxe/pxe_tftp.c Vedi File

@@ -78,6 +78,37 @@ static void pxe_tftp_build_uri ( char *uri_string,
78 78
 		   ( ( filename[0] == '/' ) ? "" : "/" ), filename );
79 79
 }
80 80
 
81
+/**
82
+ * Read as much as possible from file
83
+ *
84
+ * @v fd				File descriptor
85
+ * @v buffer				Data buffer
86
+ * @v max_len				Maximum length to read
87
+ * @ret len				Actual length read, or negative error
88
+ */
89
+static ssize_t pxe_tftp_read_all ( int fd, userptr_t buffer,
90
+				   size_t max_len ) {
91
+	fd_set fdset;
92
+	off_t offset = 0;
93
+	int ready;
94
+	ssize_t len;
95
+
96
+	do {
97
+		FD_ZERO ( &fdset );
98
+		FD_SET ( fd, &fdset );
99
+		ready = select ( &fdset, 1 );
100
+		if ( ready < 0 )
101
+			return ready;
102
+		len = read_user ( fd, buffer, offset, max_len );
103
+		if ( len < 0 )
104
+			return len;
105
+		offset += len;
106
+	        max_len -= len;
107
+	} while ( max_len && len );
108
+
109
+	return offset;
110
+}
111
+
81 112
 /**
82 113
  * TFTP OPEN
83 114
  *
@@ -251,11 +282,12 @@ PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ) {
251 282
 
252 283
 	buffer = real_to_user ( tftp_read->Buffer.segment,
253 284
 				tftp_read->Buffer.offset );
254
-	len = read_user ( pxe_single_fd, buffer, 0, pxe_single_blksize );
285
+	len = pxe_tftp_read_all ( pxe_single_fd, buffer, pxe_single_blksize );
255 286
 	if ( len < 0 ) {
256 287
 		tftp_read->Status = PXENV_STATUS ( len );
257 288
 		return PXENV_EXIT_FAILURE;
258 289
 	}
290
+
259 291
 	tftp_read->BufferSize = len;
260 292
 	tftp_read->PacketNumber = ++pxe_single_blkidx;
261 293
 
@@ -359,10 +391,8 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
359 391
 	char uri_string[PXE_URI_LEN];
360 392
 	int fd;
361 393
 	userptr_t buffer;
362
-	size_t max_len;
363
-	ssize_t frag_len;
364
-	size_t len = 0;
365
-	int rc = -ENOBUFS;
394
+	ssize_t len;
395
+	int rc = 0;
366 396
 
367 397
 	DBG ( "PXENV_TFTP_READ_FILE" );
368 398
 
@@ -384,16 +414,9 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
384 414
 
385 415
 	/* Read file */
386 416
 	buffer = phys_to_user ( tftp_read_file->Buffer );
387
-	max_len = tftp_read_file->BufferSize;
388
-	while ( max_len ) {
389
-		frag_len = read_user ( fd, buffer, len, max_len );
390
-		if ( frag_len <= 0 ) {
391
-			rc = frag_len;
392
-			break;
393
-		}
394
-		len += frag_len;
395
-		max_len -= frag_len;
396
-	}
417
+	len = pxe_tftp_read_all ( fd, buffer, tftp_read_file->BufferSize );
418
+	if ( len < 0 )
419
+		rc = len;
397 420
 
398 421
 	close ( fd );
399 422
 	tftp_read_file->BufferSize = len;

Loading…
Annulla
Salva