Browse Source

Update buffer-handling code to enable expandable buffers.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
e2dcd05b67
6 changed files with 191 additions and 295 deletions
  1. 0
    69
      src/arch/i386/core/load_buffer.c
  2. 138
    140
      src/core/buffer.c
  3. 0
    1
      src/core/image.c
  4. 52
    45
      src/include/gpxe/buffer.h
  5. 0
    39
      src/include/load_buffer.h
  6. 1
    1
      src/proto/slam.c

+ 0
- 69
src/arch/i386/core/load_buffer.c View File

@@ -1,69 +0,0 @@
1
-#include "io.h"
2
-#include "load_buffer.h"
3
-
4
-/*
5
- * Initialise a buffer in an unused portion of memory, to be used for
6
- * loading an image
7
- *
8
- */
9
-
10
-#ifdef KEEP_IT_REAL
11
-
12
-/*
13
- * Under KEEP_IT_REAL, always use 07c0:0000 as the load buffer.
14
- *
15
- */
16
-
17
-int init_load_buffer ( struct buffer *buffer ) {
18
-	buffer->start = 0x7c00;
19
-	buffer->end = 0xa0000;
20
-	DBG ( "LOAD_BUFFER using [%x,%x)\n", buffer->start, buffer->end );
21
-	init_buffer ( buffer );
22
-	return 1;
23
-}
24
-
25
-void trim_load_buffer ( struct buffer *buffer ) {
26
-	/* Nothing to do */
27
-}
28
-
29
-void done_load_buffer ( struct buffer *buffer ) {
30
-	/* Nothing to do */
31
-}
32
-
33
-#else /* KEEP_IT_REAL */
34
-
35
-/*
36
- * Without KEEP_IT_REAL, use all remaining heap space as the load buffer.
37
- *
38
- */
39
-int init_load_buffer ( struct buffer *buffer ) {
40
-	void *data;
41
-	size_t size;
42
-	
43
-	data = emalloc_all ( &size );
44
-	if ( ! data )
45
-		return 0;
46
-
47
-	buffer->start = virt_to_phys ( data );
48
-	buffer->end = buffer->start + size;
49
-	DBG ( "LOAD_BUFFER using [%x,%x)\n", buffer->start, buffer->end );
50
-	init_buffer ( buffer );
51
-	return 1;
52
-}
53
-
54
-void trim_load_buffer ( struct buffer *buffer ) {
55
-	void *new_start;
56
-
57
-	/* Shrink buffer */
58
-	new_start = erealloc ( phys_to_virt ( buffer->start ), buffer->fill );
59
-	DBG ( "LOAD_BUFFER shrunk from [%x,%x) to [%x,%x)\n", buffer->start,
60
-	      buffer->end, virt_to_phys ( new_start ), buffer->end );
61
-	buffer->start = virt_to_phys ( new_start );
62
-}
63
-
64
-void done_load_buffer ( struct buffer *buffer ) {
65
-	efree ( phys_to_virt ( buffer->start ) );
66
-	DBG ( "LOAD_BUFFER freed [%x,%x)\n", buffer->start, buffer->end );
67
-}
68
-
69
-#endif

+ 138
- 140
src/core/buffer.c View File

@@ -1,3 +1,27 @@
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stddef.h>
20
+#include <string.h>
21
+#include <errno.h>
22
+#include <assert.h>
23
+#include <io.h>
24
+#include <gpxe/buffer.h>
1 25
 
2 26
 /** @file
3 27
  *
@@ -7,27 +31,22 @@
7 31
  * which is "filled" and the remainder of which is "free".  The
8 32
  * "filled" and "free" spaces are not necessarily contiguous.
9 33
  *
10
- * When a buffer is initialised via init_buffer(), it consists of a
11
- * single free space.  As data is added to the buffer via
12
- * fill_buffer(), this free space decreases and can become fragmented.
13
- *
14
- * Each free block within a buffer starts with a "tail byte".  If the
15
- * tail byte is non-zero, this indicates that the free block is the
16
- * tail of the buffer, i.e. occupies all the remaining space up to the
17
- * end of the buffer.  When the tail byte is non-zero, it indicates
18
- * that a descriptor (a @c struct @c buffer_free_block) follows the
19
- * tail byte.  The descriptor describes the size of the free block and
20
- * the address of the next free block.
21
- *
22
- * We cannot simply always start a free block with a descriptor,
23
- * because it is conceivable that we will, at some point, encounter a
24
- * situation in which the final free block of a buffer is too small to
25
- * contain a descriptor.  Consider a protocol with a blocksize of 512
26
- * downloading a 1025-byte file into a 1025-byte buffer.  Suppose that
27
- * the first two blocks are received; we have now filled 1024 of the
28
- * 1025 bytes in the buffer, and our only free block consists of the
29
- * 1025th byte.  Using a "tail byte" solves this problem.
30
- *
34
+ * At the start of a buffer's life, it consists of a single free
35
+ * space.  As data is added to the buffer via fill_buffer(), this free
36
+ * space decreases and can become fragmented.
37
+ *
38
+ * Each free block within a buffer (except the last) starts with a @c
39
+ * struct @c buffer_free_block.  This describes the size of the free
40
+ * block, and the offset to the next free block.
41
+ *
42
+ * We cannot simply start every free block (including the last) with a
43
+ * descriptor, because it is conceivable that we will, at some point,
44
+ * encounter a situation in which the final free block of a buffer is
45
+ * too small to contain a descriptor.  Consider a protocol with a
46
+ * blocksize of 512 downloading a 1025-byte file into a 1025-byte
47
+ * buffer.  Suppose that the first two blocks are received; we have
48
+ * now filled 1024 of the 1025 bytes in the buffer, and our only free
49
+ * block consists of the 1025th byte.
31 50
  * 
32 51
  * Note that the rather convoluted way of manipulating the buffer
33 52
  * descriptors (using copy_{to,from}_phys rather than straightforward
@@ -38,107 +57,76 @@
38 57
  *
39 58
  */
40 59
 
41
-#include "stddef.h"
42
-#include "string.h"
43
-#include "io.h"
44
-#include "errno.h"
45
-#include <assert.h>
46
-#include <gpxe/buffer.h>
47
-
48 60
 /**
49
- * Initialise a buffer.
61
+ * A free block descriptor
50 62
  *
51
- * @v buffer		The buffer to be initialised
52
- * @ret None		-
53
- * @err None		-
63
+ * This is the data structure that is found at the start of a free
64
+ * block within a data buffer.
65
+ */
66
+struct buffer_free_block {
67
+	/** Starting offset of the free block */
68
+	size_t start;
69
+	/** Ending offset of the free block */
70
+	size_t end;
71
+	/** Offset of next free block */
72
+	size_t next;
73
+};
74
+
75
+/**
76
+ * Get next free block within the buffer
54 77
  *
55
- * Set @c buffer->start and @c buffer->end before calling init_buffer().
56
- * init_buffer() will initialise the buffer to the state of being
57
- * empty.
78
+ * @v buffer		Data buffer
79
+ * @v block		Previous free block descriptor
80
+ * @ret block		Next free block descriptor
81
+ * @ret rc		Return status code
58 82
  *
83
+ * Set @c block->next=buffer->free before first call to
84
+ * get_next_free_block().
59 85
  */
60
-void init_buffer ( struct buffer *buffer ) {
61
-	char tail = 1;
62
-
63
-	buffer->fill = 0;
64
-	if ( buffer->end != buffer->start )
65
-		copy_to_phys ( buffer->start, &tail, sizeof ( tail ) );
86
+static int get_next_free_block ( struct buffer *buffer,
87
+				 struct buffer_free_block *block ) {
66 88
 
67
-	DBG ( "BUFFER [%x,%x) initialised\n", buffer->start, buffer->end );
68
-}
89
+	/* Check for end of buffer */
90
+	if ( block->end >= buffer->len )
91
+		return -ENOENT;
69 92
 
70
-/**
71
- * Move to the next block in the free list
72
- *
73
- * @v block		The current free block
74
- * @v buffer		The buffer
75
- * @ret True		Successfully moved to the next free block
76
- * @ret False		There are no more free blocks
77
- * @ret block		The next free block
78
- * @err None		-
79
- *
80
- * Move to the next block in the free block list, filling in @c block
81
- * with the descriptor for this next block.  If the next block is the
82
- * tail block, @c block will be filled with the values calculated for
83
- * the tail block, otherwise the descriptor will be read from the free
84
- * block itself.
85
- *
86
- * If there are no more free blocks, next_free_block() returns False
87
- * and leaves @c block with invalid contents.
88
- *
89
- * Set <tt> block->next = buffer->start + buffer->fill </tt> for the
90
- * first call to next_free_block().
91
- */
92
-static inline int next_free_block ( struct buffer_free_block *block,
93
-				    struct buffer *buffer ) {
94 93
 	/* Move to next block */
95 94
 	block->start = block->next;
96
-
97
-	/* If at end of buffer, return 0 */
98
-	if ( block->start >= buffer->end )
99
-		return 0;
100
-
101
-	/* Set up ->next and ->end as for a tail block */
102
-	block->next = block->end = buffer->end;
103
-
104
-	/* Read tail marker from block */
105
-	copy_from_phys ( &block->tail, block->start, sizeof ( block->tail ) );
106
-
107
-	/* If not a tail block, read whole block descriptor from block */
108
-	if ( ! block->tail ) {
109
-		copy_from_phys ( block, block->start, sizeof ( *block ) );
95
+	if ( block->start >= buffer->free ) {
96
+		/* Final block; no in-band descriptor */
97
+		block->end = buffer->len;
98
+	} else {
99
+		/* Retrieve block descriptor */
100
+		copy_from_phys ( block, ( buffer->addr + block->start ),
101
+				 sizeof ( *block ) );
110 102
 	}
111 103
 
112
-	return 1;
104
+	return 0;
113 105
 }
114 106
 
115 107
 /**
116
- * Store a free block descriptor
108
+ * Write free block descriptor back to buffer
117 109
  *
118
- * @v block		The free block descriptor to store
119
- * @ret None		-
120
- * @err None		-
121
- *
122
- * Writes a free block descriptor back to a free block.  If the block
123
- * is a tail block, only the tail marker will be written, otherwise
124
- * the whole block descriptor will be written.
110
+ * @v buffer		Data buffer
111
+ * @v block		Free block descriptor
125 112
  */
126
-static inline void store_free_block ( struct buffer_free_block *block ) {
127
-	copy_to_phys ( block->start, block,
128
-		       ( block->tail ?
129
-			 sizeof ( block->tail ) : sizeof ( *block ) ) );
113
+static void store_free_block ( struct buffer *buffer,
114
+			       struct buffer_free_block *block ) {
115
+	size_t free_block_size = ( block->end - block->start );
116
+
117
+	assert ( free_block_size >= sizeof ( *block ) );
118
+	copy_to_phys ( ( buffer->addr + block->start ), block,
119
+		       sizeof ( *block ) );
130 120
 }
131 121
 
132 122
 /**
133
- * Write data into a buffer.
123
+ * Write data into a buffer
134 124
  *
135
- * @v buffer		The buffer into which to write the data
136
- * @v data		The data to be written
125
+ * @v buffer		Data buffer
126
+ * @v data		Data to be written
137 127
  * @v offset		Offset within the buffer at which to write the data
138 128
  * @v len		Length of data to be written
139
- * @ret True		Data was successfully written
140
- * @ret False		Data was not written
141
- * @err ENOMEM		Buffer is too small to contain the data
129
+ * @ret rc		Return status code
142 130
  *
143 131
  * Writes a block of data into the buffer.  The block need not be
144 132
  * aligned to any particular boundary, or be of any particular size,
@@ -166,29 +154,37 @@ static inline void store_free_block ( struct buffer_free_block *block ) {
166 154
  *
167 155
  */
168 156
 int fill_buffer ( struct buffer *buffer, const void *data,
169
-		  off_t offset, size_t len ) {
157
+		  size_t offset, size_t len ) {
170 158
 	struct buffer_free_block block, before, after;
171
-	physaddr_t data_start, data_end;
172
-
173
-	/* Calculate start and end addresses of data */
174
-	data_start = buffer->start + offset;
175
-	data_end = data_start + len;
176
-	DBG ( "BUFFER [%x,%x) writing portion [%x,%x)\n",
177
-	      buffer->start, buffer->end, data_start, data_end );
178
-
179
-	/* Check buffer bounds */
180
-	if ( data_end > buffer->end ) {
181
-		DBG ( "BUFFER [%x,%x) too small for data!\n",
182
-		      buffer->start, buffer->end );
183
-		errno = ENOMEM;
184
-		return 0;
159
+	size_t data_start = offset;
160
+	size_t data_end = ( data_start + len );
161
+	int rc;
162
+
163
+	DBGC ( buffer, "BUFFER %p [%lx,%lx) filling portion [%lx,%lx)\n",
164
+	       buffer, buffer->addr, ( buffer->addr + buffer->len ),
165
+	       ( buffer->addr + data_start ), ( buffer->addr + data_end ) );
166
+
167
+	/* Check that block fits within buffer, expand if necessary */
168
+	if ( data_end > buffer->len ) {
169
+		if ( ! buffer->expand ) {
170
+			DBGC ( buffer, "BUFFER %p not expandable\n", buffer );
171
+			return -ENOBUFS;
172
+		}
173
+		if ( ( rc = buffer->expand ( buffer, data_end ) ) != 0 ) {
174
+			DBGC ( buffer, "BUFFER %p could not expand :%s\n",
175
+			       buffer, strerror ( rc ) );
176
+			return rc;
177
+		}
178
+		DBGC ( buffer, "BUFFER %p expanded to [%lx,%lx)\n", buffer,
179
+		       buffer->addr, ( buffer->addr + buffer->len ) );
180
+		assert ( buffer->len >= data_end );
185 181
 	}
186 182
 
187 183
 	/* Find 'before' and 'after' blocks, if any */
188 184
 	before.start = before.end = 0;
189
-	after.start = after.end = buffer->end;
190
-	block.next = buffer->start + buffer->fill;
191
-	while ( next_free_block ( &block, buffer ) ) {
185
+	after.start = after.end = buffer->len;
186
+	block.next = buffer->fill;
187
+	while ( get_next_free_block ( buffer, &block ) == 0 ) {
192 188
 		if ( ( block.start < data_start ) &&
193 189
 		     ( block.start >= before.start ) )
194 190
 			memcpy ( &before, &block, sizeof ( before ) );
@@ -206,33 +202,35 @@ int fill_buffer ( struct buffer *buffer, const void *data,
206 202
 	/* Link 'after' block to 'before' block */
207 203
 	before.next = after.start;
208 204
 
205
+	DBGC ( buffer, "BUFFER %p split before [%lx,%lx) after [%lx,%lx)\n",
206
+	       buffer, ( buffer->addr + before.start ),
207
+	       ( buffer->addr + before.end ), ( buffer->addr + after.start ),
208
+	       ( buffer->addr + after.end ) );
209
+
209 210
 	/* Write back 'before' block, if any */
210
-	if ( before.start ) {
211
-		before.tail = 0;
212
-		assert ( ( before.end - before.start ) >=
213
-			 sizeof ( struct buffer_free_block ) );
214
-		store_free_block ( &before );
211
+	if ( before.end == 0 ) {
212
+		/* No 'before' block: update buffer->fill */
213
+		buffer->fill = after.start;
214
+		DBGC ( buffer, "BUFFER %p full up to %lx\n", buffer,
215
+		       ( buffer->addr + buffer->fill ) );
215 216
 	} else {
216
-		buffer->fill = before.next - buffer->start;
217
+		/* Write back 'before' block */
218
+		store_free_block ( buffer, &before );
217 219
 	}
218 220
 
219
-	/* Write back 'after' block, if any */
220
-	if ( after.start < buffer->end ) {
221
-		assert ( after.tail ||
222
-			 ( ( after.end - after.start ) >=
223
-			   sizeof ( struct buffer_free_block ) ) );
224
-		store_free_block ( &after );
221
+	/* Write back 'after' block */
222
+	if ( after.end == buffer->len ) {
223
+		/* 'After' block is the final block: update buffer->free */
224
+		buffer->free = after.start;
225
+		DBGC ( buffer, "BUFFER %p free from %lx onwards\n", buffer,
226
+		       ( buffer->addr + buffer->free ) );
227
+	} else {
228
+		/* Write back 'after' block */
229
+		store_free_block ( buffer, &after );
225 230
 	}
226
-	
227
-	DBG ( "BUFFER [%x,%x) before [%x,%x) after [%x,%x)\n",
228
-	      buffer->start, buffer->end, before.start, before.end,
229
-	      after.start, after.end );
230
-	
231
-	/* Copy data into buffer */
232
-	copy_to_phys ( data_start, data, len );
233 231
 
234
-	DBG ( "BUFFER [%x,%x) full up to %x\n",
235
-	      buffer->start, buffer->end, buffer->start + buffer->fill );
232
+	/* Copy data into buffer */
233
+	copy_to_phys ( ( buffer->addr + data_start ), data, len );
236 234
 
237
-	return 1;
235
+	return 0;
238 236
 }

+ 0
- 1
src/core/image.c View File

@@ -1,6 +1,5 @@
1 1
 #include "dev.h"
2 2
 #include <gpxe/buffer.h>
3
-#include "load_buffer.h"
4 3
 #include "image.h"
5 4
 #include <console.h>
6 5
 

+ 52
- 45
src/include/gpxe/buffer.h View File

@@ -1,8 +1,8 @@
1 1
 #ifndef _GPXE_BUFFER_H
2 2
 #define _GPXE_BUFFER_H
3 3
 
4
-#include "compiler.h" /* for doxygen */
5
-#include "stdint.h"
4
+#include <stdint.h>
5
+#include <io.h>
6 6
 
7 7
 /** @file
8 8
  *
@@ -15,14 +15,8 @@
15 15
  * Some protocols do not provide a mechanism for us to know the size
16 16
  * of the file before we happen to receive a particular block
17 17
  * (e.g. the final block in an MTFTP transfer).  In addition, some
18
- * protocols (all the multicast protocols plus any TCP-based protocol)
19
- * can, in theory, provide the data in any order.
20
- *
21
- * Rather than requiring each protocol to implement its own equivalent
22
- * of "dd" to arrange the data into well-sized pieces before handing
23
- * off to the image loader, we provide these generic buffer functions
24
- * which assemble a file into a single contiguous block.  The whole
25
- * block is then passed to the image loader.
18
+ * protocols (e.g. the multicast protocols) can, in theory, provide
19
+ * the data in any order.
26 20
  *
27 21
  * Example usage:
28 22
  *
@@ -33,65 +27,78 @@
33 27
  *   off_t offset;
34 28
  *   size_t len;
35 29
  *   
36
- *   // We have an area of memory [buf_start,buf_end) into which we want
37
- *   // to load a file, where buf_start and buf_end are physical addresses.
30
+ *   // We have an area of memory [buf_start,buf_start+len) into which to
31
+ *   // load a file, where buf_start is a physical addresse.
32
+ *   memset ( &buffer, 0, sizeof ( buffer ) );
38 33
  *   buffer->start = buf_start;
39
- *   buffer->end = buf_end;
40
- *   init_buffer ( &buffer );
34
+ *   buffer->len = len;
41 35
  *   ...
42 36
  *   while ( get_file_block ( ... ) ) {
43 37
  *     // Downloaded block is stored in [data,data+len), and represents 
44 38
  *     // the portion of the file at offsets [offset,offset+len)
45
- *     if ( ! fill_buffer ( &buffer, data, offset, len ) ) {
39
+ *     if ( fill_buffer ( &buffer, data, offset, len ) != 0 ) {
46 40
  *       // An error occurred
47
- *       return 0;
48 41
  *     }
49 42
  *     ...
50 43
  *   }
51 44
  *   ...
52 45
  *   // The whole file is now present at [buf_start,buf_start+filesize),
53 46
  *   // where buf_start is a physical address.  The struct buffer can simply
54
- *   // be discarded; there is no done_buffer() call.
47
+ *   // be discarded.
55 48
  *
56 49
  * @endcode
57 50
  *
58
- * For a description of the internal operation, see buffer.c.
59
- *
60 51
  */
61 52
 
62 53
 /**
63
- * A buffer
54
+ * A data buffer
64 55
  *
65
- * #start and #end denote the real boundaries of the buffer, and are
66
- * physical addresses.  #fill denotes the offset to the first free
67
- * block in the buffer.  (If the buffer is full, #fill will equal
68
- * #end-#start.)
56
+ * A buffer looks something like this:
69 57
  *
70
- */
71
-struct buffer {
72
-	physaddr_t	start;		/**< Start of buffer in memory */
73
-	physaddr_t	end;		/**< End of buffer in memory */
74
-	off_t		fill;		/**< Offset to first gap in buffer */
75
-};
76
-
77
-/**
78
- * A free block descriptor.
58
+ * @code
59
+ *
60
+ *     XXXXXXXXXXXXXXXXX.........XXX..........XXXXXXX........XXXXXX.........
79 61
  *
80
- * See buffer.c for a full description of the fields.
62
+ *     ^
63
+ *     |
64
+ *   start
65
+ *
66
+ *     <----- fill ---->
67
+ *
68
+ *     <------------------------ free ---------------------------->
69
+ *
70
+ *     <------------------------------ len -------------------------------->
71
+ *
72
+ * @endcode
73
+ *
74
+ * #start and #len denote the real boundaries of the buffer.  #fill
75
+ * denotes the offset to the first free block in the buffer.  (If the
76
+ * buffer is full, #fill, #free and #len will all be equal.)
81 77
  *
82 78
  */
83
-struct buffer_free_block {
84
-	char		tail;		/**< Tail byte marker */
85
-	char		reserved[3];	/**< Padding */
86
-	physaddr_t	start;		/**< Address of this free block */
87
-	physaddr_t	next;		/**< Address of next free block */
88
-	physaddr_t	end;		/**< End of this block */
89
-} __attribute__ (( packed ));
90
-
91
-/* Functions in buffer.c */
79
+struct buffer {
80
+	/** Physical start address of buffer */
81
+	physaddr_t addr;
82
+	/** Total length of buffer */
83
+	size_t len;
84
+	/** Offset to first free block within buffer */
85
+	size_t fill;
86
+	/** Offset to last free block within buffer */
87
+	size_t free;
88
+	/** Expand data buffer
89
+	 *
90
+	 * @v buffer		Data buffer
91
+	 * @v new_len		New length
92
+	 * @ret rc		Return status code
93
+	 *
94
+	 * Expand the data buffer to accommodate more data.  This
95
+	 * method is optional; if it is @c NULL then the buffer will
96
+	 * not be expandable.
97
+	 */
98
+	int ( * expand ) ( struct buffer *buffer, size_t new_len );
99
+};
92 100
 
93
-extern void init_buffer ( struct buffer *buffer );
94 101
 extern int fill_buffer ( struct buffer *buffer, const void *data,
95
-			 off_t offset, size_t len );
102
+			 size_t offset, size_t len );
96 103
 
97 104
 #endif /* _GPXE_BUFFER_H */

+ 0
- 39
src/include/load_buffer.h View File

@@ -1,39 +0,0 @@
1
-#ifndef LOAD_BUFFER_H
2
-#define LOAD_BUFFER_H
3
-
4
-#include <gpxe/buffer.h>
5
-
6
-/*
7
- * These functions are architecture-dependent, but the interface must
8
- * be identical between architectures.
9
- *
10
- */
11
-
12
-/*
13
- * Initialise a buffer suitable for loading an image.  Pass in a
14
- * pointer to an uninitialised struct buffer.
15
- *
16
- * Note that this function may (for example) allocate all remaining
17
- * allocatable memory, so it must be called *after* any other code
18
- * that might want to allocate memory (e.g. device driver
19
- * initialisation).
20
- *
21
- */
22
-extern int init_load_buffer ( struct buffer *buffer );
23
-
24
-/*
25
- * Cut a load buffer down to size once the image has been loaded.
26
- * This will shrink the buffer down to the size of the data contained
27
- * within the buffer, freeing up unused memory if applicable.
28
- *
29
- */
30
-extern void trim_load_buffer ( struct buffer *buffer );
31
-
32
-/*
33
- * Finish using a load buffer, once the image has been moved into its
34
- * target location in memory.
35
- *
36
- */
37
-extern void done_load_buffer ( struct buffer *buffer );
38
-
39
-#endif /* LOAD_BUFFER_H */

+ 1
- 1
src/proto/slam.c View File

@@ -314,7 +314,7 @@ static unsigned char *reinit_slam_state(
314 314
 		return 0;
315 315
 	}
316 316
 	bitmap_len   = (state.total_packets + 1 + 7)/8;
317
-	state.image  = phys_to_virt ( state.buffer->start );
317
+	state.image  = phys_to_virt ( state.buffer->addr );
318 318
 	/* We don't use the buffer routines properly yet; fake it */
319 319
 	state.buffer->fill = total_bytes;
320 320
 	state.bitmap = state.image + total_bytes;

Loading…
Cancel
Save