|  | @@ -4,22 +4,44 @@
 | 
		
	
		
			
			| 4 | 4 |  #include "gateA20.h"
 | 
		
	
		
			
			| 5 | 5 |  #include "osloader.h"
 | 
		
	
		
			
			| 6 | 6 |  #include "etherboot.h"
 | 
		
	
		
			
			|  | 7 | +#include "errno.h"
 | 
		
	
		
			
			| 7 | 8 |  
 | 
		
	
		
			
			| 8 |  | -/* An NBI image header */
 | 
		
	
		
			
			|  | 9 | +/** @file
 | 
		
	
		
			
			|  | 10 | + *
 | 
		
	
		
			
			|  | 11 | + * NBI image format.
 | 
		
	
		
			
			|  | 12 | + *
 | 
		
	
		
			
			|  | 13 | + * The Net Boot Image format is defined by the "Draft Net Boot Image
 | 
		
	
		
			
			|  | 14 | + * Proposal 0.3" by Jamie Honan, Gero Kuhlmann and Ken Yap.  It is now
 | 
		
	
		
			
			|  | 15 | + * considered to be a legacy format, but it still included because a
 | 
		
	
		
			
			|  | 16 | + * large amount of software (e.g. nymph, LTSP) makes use of NBI files.
 | 
		
	
		
			
			|  | 17 | + *
 | 
		
	
		
			
			|  | 18 | + * Etherboot does not implement the INT 78 callback interface
 | 
		
	
		
			
			|  | 19 | + * described by the NBI specification.  For a callback interface on
 | 
		
	
		
			
			|  | 20 | + * x86 architecture, use PXE.
 | 
		
	
		
			
			|  | 21 | + *
 | 
		
	
		
			
			|  | 22 | + */
 | 
		
	
		
			
			|  | 23 | +
 | 
		
	
		
			
			|  | 24 | +/**
 | 
		
	
		
			
			|  | 25 | + * An NBI image header
 | 
		
	
		
			
			|  | 26 | + *
 | 
		
	
		
			
			|  | 27 | + * Note that the length field uses a peculiar encoding; use the
 | 
		
	
		
			
			|  | 28 | + * NBI_LENGTH() macro to decode the actual header length.
 | 
		
	
		
			
			|  | 29 | + *
 | 
		
	
		
			
			|  | 30 | + */
 | 
		
	
		
			
			| 9 | 31 |  struct imgheader {
 | 
		
	
		
			
			| 10 |  | -	unsigned long magic;
 | 
		
	
		
			
			|  | 32 | +	unsigned long magic;		/**< Magic number (NBI_MAGIC) */
 | 
		
	
		
			
			| 11 | 33 |  	union {
 | 
		
	
		
			
			| 12 |  | -		unsigned char length;
 | 
		
	
		
			
			| 13 |  | -		unsigned long flags;
 | 
		
	
		
			
			|  | 34 | +		unsigned char length;	/**< Nibble-coded header length */
 | 
		
	
		
			
			|  | 35 | +		unsigned long flags;	/**< Image flags */
 | 
		
	
		
			
			| 14 | 36 |  	};
 | 
		
	
		
			
			| 15 |  | -	segoff_t location;
 | 
		
	
		
			
			|  | 37 | +	segoff_t location;		/**< 16-bit seg:off header location */
 | 
		
	
		
			
			| 16 | 38 |  	union {
 | 
		
	
		
			
			| 17 |  | -		segoff_t segoff;
 | 
		
	
		
			
			| 18 |  | -		unsigned long linear;
 | 
		
	
		
			
			|  | 39 | +		segoff_t segoff;	/**< 16-bit seg:off entry point */
 | 
		
	
		
			
			|  | 40 | +		unsigned long linear;	/**< 32-bit entry point */
 | 
		
	
		
			
			| 19 | 41 |  	} execaddr;
 | 
		
	
		
			
			| 20 | 42 |  } __attribute__ (( packed ));
 | 
		
	
		
			
			| 21 | 43 |  
 | 
		
	
		
			
			| 22 |  | -/* NBI magic number */
 | 
		
	
		
			
			|  | 44 | +/** NBI magic number */
 | 
		
	
		
			
			| 23 | 45 |  #define NBI_MAGIC 0x1B031336UL
 | 
		
	
		
			
			| 24 | 46 |  
 | 
		
	
		
			
			| 25 | 47 |  /* Interpretation of the "length" fields */
 | 
		
	
	
		
			
			|  | @@ -31,18 +53,24 @@ struct imgheader {
 | 
		
	
		
			
			| 31 | 53 |  #define	NBI_PROGRAM_RETURNS(flags)	( (flags) & ( 1 << 8 ) )
 | 
		
	
		
			
			| 32 | 54 |  #define	NBI_LINEAR_EXEC_ADDR(flags)	( (flags) & ( 1 << 31 ) )
 | 
		
	
		
			
			| 33 | 55 |  
 | 
		
	
		
			
			| 34 |  | -/* NBI header length */
 | 
		
	
		
			
			|  | 56 | +/** NBI header length */
 | 
		
	
		
			
			| 35 | 57 |  #define NBI_HEADER_LENGTH	512
 | 
		
	
		
			
			| 36 | 58 |  
 | 
		
	
		
			
			| 37 |  | -/* An NBI segment header */
 | 
		
	
		
			
			|  | 59 | +/**
 | 
		
	
		
			
			|  | 60 | + * An NBI segment header
 | 
		
	
		
			
			|  | 61 | + *
 | 
		
	
		
			
			|  | 62 | + * Note that the length field uses a peculiar encoding; use the
 | 
		
	
		
			
			|  | 63 | + * NBI_LENGTH() macro to decode the actual header length.
 | 
		
	
		
			
			|  | 64 | + *
 | 
		
	
		
			
			|  | 65 | + */
 | 
		
	
		
			
			| 38 | 66 |  struct segheader {
 | 
		
	
		
			
			| 39 |  | -	unsigned char length;
 | 
		
	
		
			
			| 40 |  | -	unsigned char vendortag;
 | 
		
	
		
			
			|  | 67 | +	unsigned char length;		/**< Nibble-coded header length */
 | 
		
	
		
			
			|  | 68 | +	unsigned char vendortag;	/**< Vendor-defined private tag */
 | 
		
	
		
			
			| 41 | 69 |  	unsigned char reserved;
 | 
		
	
		
			
			| 42 |  | -	unsigned char flags;
 | 
		
	
		
			
			| 43 |  | -	unsigned long loadaddr;
 | 
		
	
		
			
			| 44 |  | -	unsigned long imglength;
 | 
		
	
		
			
			| 45 |  | -	unsigned long memlength;
 | 
		
	
		
			
			|  | 70 | +	unsigned char flags;		/**< Segment flags */
 | 
		
	
		
			
			|  | 71 | +	unsigned long loadaddr;		/**< Load address */
 | 
		
	
		
			
			|  | 72 | +	unsigned long imglength;	/**< Segment length in NBI file */
 | 
		
	
		
			
			|  | 73 | +	unsigned long memlength;	/**< Segment length in memory */
 | 
		
	
		
			
			| 46 | 74 |  };
 | 
		
	
		
			
			| 47 | 75 |  
 | 
		
	
		
			
			| 48 | 76 |  /* Interpretation of the "flags" fields */
 | 
		
	
	
		
			
			|  | @@ -53,28 +81,41 @@ struct segheader {
 | 
		
	
		
			
			| 53 | 81 |  #define NBI_LOADADDR_BEFORE		0x03
 | 
		
	
		
			
			| 54 | 82 |  #define NBI_LAST_SEGHEADER(flags)	( (flags) & ( 1 << 2 ) )
 | 
		
	
		
			
			| 55 | 83 |  
 | 
		
	
		
			
			| 56 |  | -/* Info passed to NBI image */
 | 
		
	
		
			
			|  | 84 | +/** Info passed to NBI image */
 | 
		
	
		
			
			| 57 | 85 |  static struct ebinfo loaderinfo = {
 | 
		
	
		
			
			| 58 | 86 |  	VERSION_MAJOR, VERSION_MINOR,
 | 
		
	
		
			
			| 59 | 87 |  	0
 | 
		
	
		
			
			| 60 | 88 |  };
 | 
		
	
		
			
			| 61 | 89 |  
 | 
		
	
		
			
			| 62 |  | -/*
 | 
		
	
		
			
			|  | 90 | +/**
 | 
		
	
		
			
			| 63 | 91 |   * Determine whether or not this is a valid NBI image
 | 
		
	
		
			
			| 64 | 92 |   *
 | 
		
	
		
			
			|  | 93 | + * @v start		Address of the image
 | 
		
	
		
			
			|  | 94 | + * @v len		Length of the image
 | 
		
	
		
			
			|  | 95 | + * @v context		NBI image context
 | 
		
	
		
			
			|  | 96 | + * @ret	True		Image is a valid NBI image
 | 
		
	
		
			
			|  | 97 | + * @ret	False		Image is not a valid NBI image
 | 
		
	
		
			
			|  | 98 | + * @err	EBADIMG		Image is not a valid NBI image
 | 
		
	
		
			
			|  | 99 | + * 
 | 
		
	
		
			
			|  | 100 | + * "context" is filled in with a context pointer suitable for passing to
 | 
		
	
		
			
			|  | 101 | + * nbi_load() and nbi_boot().
 | 
		
	
		
			
			|  | 102 | + *
 | 
		
	
		
			
			| 65 | 103 |   */
 | 
		
	
		
			
			| 66 | 104 |  static int nbi_probe ( physaddr_t start, off_t len, void **context ) {
 | 
		
	
		
			
			| 67 | 105 |  	static struct imgheader imgheader;
 | 
		
	
		
			
			| 68 | 106 |  
 | 
		
	
		
			
			| 69 | 107 |  	if ( (unsigned)len < sizeof ( imgheader ) ) {
 | 
		
	
		
			
			| 70 | 108 |  		DBG ( "NBI image too small\n" );
 | 
		
	
		
			
			|  | 109 | +		errno = EBADIMG;
 | 
		
	
		
			
			| 71 | 110 |  		return 0;
 | 
		
	
		
			
			| 72 | 111 |  	}
 | 
		
	
		
			
			| 73 | 112 |  
 | 
		
	
		
			
			| 74 | 113 |  	copy_from_phys ( &imgheader, start, sizeof ( imgheader ) );
 | 
		
	
		
			
			| 75 | 114 |  
 | 
		
	
		
			
			| 76 |  | -	if ( imgheader.magic != NBI_MAGIC )
 | 
		
	
		
			
			|  | 115 | +	if ( imgheader.magic != NBI_MAGIC ) {
 | 
		
	
		
			
			|  | 116 | +		errno = EBADIMG;
 | 
		
	
		
			
			| 77 | 117 |  		return 0;
 | 
		
	
		
			
			|  | 118 | +	}
 | 
		
	
		
			
			| 78 | 119 |  
 | 
		
	
		
			
			| 79 | 120 |  	/* Record image context */
 | 
		
	
		
			
			| 80 | 121 |  	DBG ( "NBI found valid image\n" );
 | 
		
	
	
		
			
			|  | @@ -82,9 +123,17 @@ static int nbi_probe ( physaddr_t start, off_t len, void **context ) {
 | 
		
	
		
			
			| 82 | 123 |  	return 1;
 | 
		
	
		
			
			| 83 | 124 |  }
 | 
		
	
		
			
			| 84 | 125 |  
 | 
		
	
		
			
			| 85 |  | -/*
 | 
		
	
		
			
			|  | 126 | +/**
 | 
		
	
		
			
			| 86 | 127 |   * Prepare a segment for an NBI image
 | 
		
	
		
			
			| 87 | 128 |   *
 | 
		
	
		
			
			|  | 129 | + * @v dest		Address of segment
 | 
		
	
		
			
			|  | 130 | + * @v imglen		Length of initialised-data portion of the segment
 | 
		
	
		
			
			|  | 131 | + * @v memlen		Total length of the segment
 | 
		
	
		
			
			|  | 132 | + * @v src		Source for initialised data
 | 
		
	
		
			
			|  | 133 | + * @ret True		Segment can be used
 | 
		
	
		
			
			|  | 134 | + * @ret False		Segment cannot be used
 | 
		
	
		
			
			|  | 135 | + * @err other		As returned by prep_segment()
 | 
		
	
		
			
			|  | 136 | + *
 | 
		
	
		
			
			| 88 | 137 |   */
 | 
		
	
		
			
			| 89 | 138 |  static int nbi_prepare_segment ( physaddr_t dest, off_t imglen, off_t memlen,
 | 
		
	
		
			
			| 90 | 139 |  				 physaddr_t src __unused ) {
 | 
		
	
	
		
			
			|  | @@ -93,9 +142,15 @@ static int nbi_prepare_segment ( physaddr_t dest, off_t imglen, off_t memlen,
 | 
		
	
		
			
			| 93 | 142 |  	return prep_segment ( dest, dest + imglen, dest + memlen );
 | 
		
	
		
			
			| 94 | 143 |  }
 | 
		
	
		
			
			| 95 | 144 |  
 | 
		
	
		
			
			| 96 |  | -/*
 | 
		
	
		
			
			|  | 145 | +/**
 | 
		
	
		
			
			| 97 | 146 |   * Load a segment for an NBI image
 | 
		
	
		
			
			| 98 | 147 |   *
 | 
		
	
		
			
			|  | 148 | + * @v dest		Address of segment
 | 
		
	
		
			
			|  | 149 | + * @v imglen		Length of initialised-data portion of the segment
 | 
		
	
		
			
			|  | 150 | + * @v memlen		Total length of the segment
 | 
		
	
		
			
			|  | 151 | + * @v src		Source for initialised data
 | 
		
	
		
			
			|  | 152 | + * @ret True		Always
 | 
		
	
		
			
			|  | 153 | + *
 | 
		
	
		
			
			| 99 | 154 |   */
 | 
		
	
		
			
			| 100 | 155 |  static int nbi_load_segment ( physaddr_t dest, off_t imglen,
 | 
		
	
		
			
			| 101 | 156 |  			      off_t memlen __unused, physaddr_t src ) {
 | 
		
	
	
		
			
			|  | @@ -104,9 +159,18 @@ static int nbi_load_segment ( physaddr_t dest, off_t imglen,
 | 
		
	
		
			
			| 104 | 159 |  	return 1;
 | 
		
	
		
			
			| 105 | 160 |  }
 | 
		
	
		
			
			| 106 | 161 |  
 | 
		
	
		
			
			| 107 |  | -/*
 | 
		
	
		
			
			|  | 162 | +/**
 | 
		
	
		
			
			| 108 | 163 |   * Process segments of an NBI image
 | 
		
	
		
			
			| 109 | 164 |   *
 | 
		
	
		
			
			|  | 165 | + * @v start		Address of the image
 | 
		
	
		
			
			|  | 166 | + * @v len		Length of the image
 | 
		
	
		
			
			|  | 167 | + * @v imgheader		Image header information
 | 
		
	
		
			
			|  | 168 | + * @v process		Function to call for each segment
 | 
		
	
		
			
			|  | 169 | + * @ret True		All segments were processed successfully
 | 
		
	
		
			
			|  | 170 | + * @ret False		An error occurred processing a segment
 | 
		
	
		
			
			|  | 171 | + * @err EBADIMG		Image is not a valid NBI image
 | 
		
	
		
			
			|  | 172 | + * @err other		As returned by the "process" function
 | 
		
	
		
			
			|  | 173 | + *
 | 
		
	
		
			
			| 110 | 174 |   */
 | 
		
	
		
			
			| 111 | 175 |  static int nbi_process_segments ( physaddr_t start, off_t len,
 | 
		
	
		
			
			| 112 | 176 |  				  struct imgheader *imgheader,
 | 
		
	
	
		
			
			|  | @@ -136,6 +200,7 @@ static int nbi_process_segments ( physaddr_t start, off_t len,
 | 
		
	
		
			
			| 136 | 200 |  		if ( sh.length == 0 ) {
 | 
		
	
		
			
			| 137 | 201 |  			/* Avoid infinite loop? */
 | 
		
	
		
			
			| 138 | 202 |  			DBG ( "NBI invalid segheader length 0\n" );
 | 
		
	
		
			
			|  | 203 | +			errno = EBADIMG;
 | 
		
	
		
			
			| 139 | 204 |  			return 0;
 | 
		
	
		
			
			| 140 | 205 |  		}
 | 
		
	
		
			
			| 141 | 206 |  		
 | 
		
	
	
		
			
			|  | @@ -159,8 +224,8 @@ static int nbi_process_segments ( physaddr_t start, off_t len,
 | 
		
	
		
			
			| 159 | 224 |  				- sh.loadaddr;
 | 
		
	
		
			
			| 160 | 225 |  			break;
 | 
		
	
		
			
			| 161 | 226 |  		default:
 | 
		
	
		
			
			| 162 |  | -			DBG ( "NBI can't count up to three\n" );
 | 
		
	
		
			
			| 163 |  | -			return 0;
 | 
		
	
		
			
			|  | 227 | +			/* Cannot be reached */
 | 
		
	
		
			
			|  | 228 | +			DBG ( "NBI can't count up to three!\n" );
 | 
		
	
		
			
			| 164 | 229 |  		}
 | 
		
	
		
			
			| 165 | 230 |  
 | 
		
	
		
			
			| 166 | 231 |  		/* Process this segment */
 | 
		
	
	
		
			
			|  | @@ -175,6 +240,7 @@ static int nbi_process_segments ( physaddr_t start, off_t len,
 | 
		
	
		
			
			| 175 | 240 |  		sh_off += NBI_LENGTH ( sh.length );
 | 
		
	
		
			
			| 176 | 241 |  		if ( sh_off >= NBI_HEADER_LENGTH ) {
 | 
		
	
		
			
			| 177 | 242 |  			DBG ( "NBI header overflow\n" );
 | 
		
	
		
			
			|  | 243 | +			errno = EBADIMG;
 | 
		
	
		
			
			| 178 | 244 |  			return 0;
 | 
		
	
		
			
			| 179 | 245 |  		}
 | 
		
	
		
			
			| 180 | 246 |  
 | 
		
	
	
		
			
			|  | @@ -183,22 +249,35 @@ static int nbi_process_segments ( physaddr_t start, off_t len,
 | 
		
	
		
			
			| 183 | 249 |  	if ( offset != len ) {
 | 
		
	
		
			
			| 184 | 250 |  		DBG ( "NBI length mismatch (file %d, metadata %d)\n",
 | 
		
	
		
			
			| 185 | 251 |  		      len, offset );
 | 
		
	
		
			
			|  | 252 | +		errno = EBADIMG;
 | 
		
	
		
			
			| 186 | 253 |  		return 0;
 | 
		
	
		
			
			| 187 | 254 |  	}
 | 
		
	
		
			
			| 188 | 255 |  
 | 
		
	
		
			
			| 189 | 256 |  	return 1;
 | 
		
	
		
			
			| 190 | 257 |  }
 | 
		
	
		
			
			| 191 | 258 |  
 | 
		
	
		
			
			| 192 |  | -/*
 | 
		
	
		
			
			|  | 259 | +/**
 | 
		
	
		
			
			| 193 | 260 |   * Load an NBI image into memory
 | 
		
	
		
			
			| 194 | 261 |   *
 | 
		
	
		
			
			|  | 262 | + * @v start		Address of image
 | 
		
	
		
			
			|  | 263 | + * @v len		Length of image
 | 
		
	
		
			
			|  | 264 | + * @v context		NBI context (as returned by nbi_probe())
 | 
		
	
		
			
			|  | 265 | + * @ret True		Image loaded into memory
 | 
		
	
		
			
			|  | 266 | + * @ret False		Image not loaded into memory
 | 
		
	
		
			
			|  | 267 | + * @err EBADIMG		Image is not a valid NBI image
 | 
		
	
		
			
			|  | 268 | + * @err other		As returned by nbi_process_segments()
 | 
		
	
		
			
			|  | 269 | + * @err other		As returned by nbi_prepare_segment()
 | 
		
	
		
			
			|  | 270 | + * @err other		As returned by nbi_load_segment()
 | 
		
	
		
			
			|  | 271 | + *
 | 
		
	
		
			
			| 195 | 272 |   */
 | 
		
	
		
			
			| 196 | 273 |  static int nbi_load ( physaddr_t start, off_t len, void *context ) {
 | 
		
	
		
			
			| 197 | 274 |  	struct imgheader *imgheader = context;
 | 
		
	
		
			
			| 198 | 275 |  
 | 
		
	
		
			
			| 199 | 276 |  	/* If we don't have enough data give up */
 | 
		
	
		
			
			| 200 |  | -	if ( len < NBI_HEADER_LENGTH )
 | 
		
	
		
			
			|  | 277 | +	if ( len < NBI_HEADER_LENGTH ) {
 | 
		
	
		
			
			|  | 278 | +		errno = EBADIMG;
 | 
		
	
		
			
			| 201 | 279 |  		return 0;
 | 
		
	
		
			
			|  | 280 | +	}
 | 
		
	
		
			
			| 202 | 281 |  	
 | 
		
	
		
			
			| 203 | 282 |  	DBG ( "NBI placing header at %hx:%hx\n",
 | 
		
	
		
			
			| 204 | 283 |  	      imgheader->location.segment, imgheader->location.offset );
 | 
		
	
	
		
			
			|  | @@ -220,9 +299,14 @@ static int nbi_load ( physaddr_t start, off_t len, void *context ) {
 | 
		
	
		
			
			| 220 | 299 |  	return 1;
 | 
		
	
		
			
			| 221 | 300 |  }
 | 
		
	
		
			
			| 222 | 301 |  
 | 
		
	
		
			
			| 223 |  | -/*
 | 
		
	
		
			
			|  | 302 | +/**
 | 
		
	
		
			
			| 224 | 303 |   * Boot a 16-bit NBI image
 | 
		
	
		
			
			| 225 | 304 |   *
 | 
		
	
		
			
			|  | 305 | + * @v imgheader		Image header information
 | 
		
	
		
			
			|  | 306 | + * @ret Never		NBI program booted successfully
 | 
		
	
		
			
			|  | 307 | + * @ret False		NBI program returned
 | 
		
	
		
			
			|  | 308 | + * @err EIMGRET		NBI program returned
 | 
		
	
		
			
			|  | 309 | + *
 | 
		
	
		
			
			| 226 | 310 |   */
 | 
		
	
		
			
			| 227 | 311 |  static int nbi_boot16 ( struct imgheader *imgheader ) {
 | 
		
	
		
			
			| 228 | 312 |  	uint16_t basemem_bootp;
 | 
		
	
	
		
			
			|  | @@ -256,12 +340,23 @@ static int nbi_boot16 ( struct imgheader *imgheader ) {
 | 
		
	
		
			
			| 256 | 340 |  		    CLOBBER ( "eax", "ecx", "edx", "ebp" ) );
 | 
		
	
		
			
			| 257 | 341 |  	BASEMEM_PARAMETER_DONE ( bootp_data );
 | 
		
	
		
			
			| 258 | 342 |  	
 | 
		
	
		
			
			|  | 343 | +	errno = EIMGRET;
 | 
		
	
		
			
			| 259 | 344 |  	return 0;
 | 
		
	
		
			
			| 260 | 345 |  }
 | 
		
	
		
			
			| 261 | 346 |  
 | 
		
	
		
			
			| 262 |  | -/*
 | 
		
	
		
			
			|  | 347 | +/**
 | 
		
	
		
			
			| 263 | 348 |   * Boot a 32-bit NBI image
 | 
		
	
		
			
			| 264 | 349 |   *
 | 
		
	
		
			
			|  | 350 | + * @v imgheader		Image header information
 | 
		
	
		
			
			|  | 351 | + * @ret False		NBI program should not have returned
 | 
		
	
		
			
			|  | 352 | + * @ret other		As returned by NBI program
 | 
		
	
		
			
			|  | 353 | + * @err EIMGRET		NBI program should not have returned
 | 
		
	
		
			
			|  | 354 | + *
 | 
		
	
		
			
			|  | 355 | + * To distinguish between the case of an NBI program returning false,
 | 
		
	
		
			
			|  | 356 | + * and an NBI program that should not have returned, check errno.
 | 
		
	
		
			
			|  | 357 | + * errno will be set to EIMGRET only if the NBI program should not
 | 
		
	
		
			
			|  | 358 | + * have returned.
 | 
		
	
		
			
			|  | 359 | + *
 | 
		
	
		
			
			| 265 | 360 |   */
 | 
		
	
		
			
			| 266 | 361 |  static int nbi_boot32 ( struct imgheader *imgheader ) {
 | 
		
	
		
			
			| 267 | 362 |  	int rc = 0;
 | 
		
	
	
		
			
			|  | @@ -270,6 +365,7 @@ static int nbi_boot32 ( struct imgheader *imgheader ) {
 | 
		
	
		
			
			| 270 | 365 |  	      imgheader->execaddr.linear );
 | 
		
	
		
			
			| 271 | 366 |  
 | 
		
	
		
			
			| 272 | 367 |  	/* no gateA20_unset for PM call */
 | 
		
	
		
			
			|  | 368 | +	errno = ENOERR;
 | 
		
	
		
			
			| 273 | 369 |  	rc = xstart32 ( imgheader->execaddr.linear,
 | 
		
	
		
			
			| 274 | 370 |  			virt_to_phys ( &loaderinfo ),
 | 
		
	
		
			
			| 275 | 371 |  			( ( imgheader->location.segment << 4 ) +
 | 
		
	
	
		
			
			|  | @@ -278,15 +374,24 @@ static int nbi_boot32 ( struct imgheader *imgheader ) {
 | 
		
	
		
			
			| 278 | 374 |  	printf ( "Secondary program returned %d\n", rc );
 | 
		
	
		
			
			| 279 | 375 |  	if ( ! NBI_PROGRAM_RETURNS ( imgheader->flags ) ) {
 | 
		
	
		
			
			| 280 | 376 |  		/* We shouldn't have returned */
 | 
		
	
		
			
			|  | 377 | +		errno = EIMGRET;
 | 
		
	
		
			
			| 281 | 378 |  		rc = 0;
 | 
		
	
		
			
			| 282 | 379 |  	}
 | 
		
	
		
			
			| 283 | 380 |  
 | 
		
	
		
			
			| 284 | 381 |  	return rc;
 | 
		
	
		
			
			| 285 | 382 |  }
 | 
		
	
		
			
			| 286 | 383 |  
 | 
		
	
		
			
			| 287 |  | -/*
 | 
		
	
		
			
			|  | 384 | +/**
 | 
		
	
		
			
			| 288 | 385 |   * Boot a loaded NBI image
 | 
		
	
		
			
			| 289 | 386 |   *
 | 
		
	
		
			
			|  | 387 | + * @v context		NBI context (as returned by nbi_probe())
 | 
		
	
		
			
			|  | 388 | + * @ret Never		NBI program booted successfully
 | 
		
	
		
			
			|  | 389 | + * @ret False		NBI program should not have returned
 | 
		
	
		
			
			|  | 390 | + * @ret other		As returned by NBI program
 | 
		
	
		
			
			|  | 391 | + * @err EIMGRET		NBI program should not have returned
 | 
		
	
		
			
			|  | 392 | + *
 | 
		
	
		
			
			|  | 393 | + * See also nbi_boot16() and nbi_boot32().
 | 
		
	
		
			
			|  | 394 | + *
 | 
		
	
		
			
			| 290 | 395 |   */
 | 
		
	
		
			
			| 291 | 396 |  static int nbi_boot ( void *context ) {
 | 
		
	
		
			
			| 292 | 397 |  	struct imgheader *imgheader = context;
 | 
		
	
	
		
			
			|  | @@ -298,6 +403,7 @@ static int nbi_boot ( void *context ) {
 | 
		
	
		
			
			| 298 | 403 |  	}
 | 
		
	
		
			
			| 299 | 404 |  }
 | 
		
	
		
			
			| 300 | 405 |  
 | 
		
	
		
			
			|  | 406 | +/** Declaration of the NBI image format */
 | 
		
	
		
			
			| 301 | 407 |  static struct image nbi_image __image = {
 | 
		
	
		
			
			| 302 | 408 |  	.name	= "NBI",
 | 
		
	
		
			
			| 303 | 409 |  	.probe	= nbi_probe,
 |