iPXE
nbi.c File Reference

NBI image format. More...

#include <string.h>
#include <errno.h>
#include <assert.h>
#include <realmode.h>
#include <memsizes.h>
#include <basemem_packet.h>
#include <ipxe/uaccess.h>
#include <ipxe/segment.h>
#include <ipxe/init.h>
#include <ipxe/netdevice.h>
#include <ipxe/fakedhcp.h>
#include <ipxe/image.h>
#include <ipxe/features.h>
#include <ipxe/version.h>

Go to the source code of this file.

Data Structures

struct  imgheader
 An NBI image header. More...
struct  segheader
 An NBI segment header. More...
struct  ebinfo

Macros

#define NBI_MAGIC   0x1B031336UL
 NBI magic number.
#define NBI_NONVENDOR_LENGTH(len)
#define NBI_VENDOR_LENGTH(len)
#define NBI_LENGTH(len)
#define NBI_PROGRAM_RETURNS(flags)
#define NBI_LINEAR_EXEC_ADDR(flags)
#define NBI_HEADER_LENGTH   512
 NBI header length.
#define NBI_LOADADDR_FLAGS(flags)
#define NBI_LOADADDR_ABS   0x00
#define NBI_LOADADDR_AFTER   0x01
#define NBI_LOADADDR_END   0x02
#define NBI_LOADADDR_BEFORE   0x03
#define NBI_LAST_SEGHEADER(flags)

Functions

 FEATURE (FEATURE_IMAGE, "NBI", DHCP_EB_FEATURE_NBI, 1)
static int nbi_prepare_segment (struct image *image, size_t offset __unused, void *dest, size_t filesz, size_t memsz)
 Prepare a segment for an NBI image.
static int nbi_load_segment (struct image *image, size_t offset, void *dest, size_t filesz, size_t memsz __unused)
 Load a segment for an NBI image.
static int nbi_process_segments (struct image *image, const struct imgheader *imgheader, int(*process)(struct image *image, size_t offset, void *dest, size_t filesz, size_t memsz))
 Process segments of an NBI image.
static int nbi_boot16 (struct image *image, const struct imgheader *imgheader)
 Boot a 16-bit NBI image.
static int nbi_boot32 (struct image *image, const struct imgheader *imgheader)
 Boot a 32-bit NBI image.
static int nbi_prepare_dhcp (struct image *image)
 Prepare DHCP parameter block for NBI image.
static int nbi_exec (struct image *image)
 Execute a loaded NBI image.
static int nbi_probe (struct image *image)
 Probe NBI image.
struct image_type nbi_image_type __image_type (PROBE_NORMAL)
 NBI image type.

Detailed Description

NBI image format.

The Net Boot Image format is defined by the "Draft Net Boot Image Proposal 0.3" by Jamie Honan, Gero Kuhlmann and Ken Yap. It is now considered to be a legacy format, but it still included because a large amount of software (e.g. nymph, LTSP) makes use of NBI files.

Etherboot does not implement the INT 78 callback interface described by the NBI specification. For a callback interface on x86 architecture, use PXE.

Definition in file nbi.c.

Macro Definition Documentation

◆ NBI_MAGIC

#define NBI_MAGIC   0x1B031336UL

NBI magic number.

Definition at line 54 of file nbi.c.

Referenced by nbi_probe().

◆ NBI_NONVENDOR_LENGTH

#define NBI_NONVENDOR_LENGTH ( len)
Value:
( ( (len) & 0x0f ) << 2 )
ring len
Length.
Definition dwmac.h:226

Definition at line 57 of file nbi.c.

◆ NBI_VENDOR_LENGTH

#define NBI_VENDOR_LENGTH ( len)
Value:
( ( (len) & 0xf0 ) >> 2 )

Definition at line 58 of file nbi.c.

◆ NBI_LENGTH

#define NBI_LENGTH ( len)
Value:
#define NBI_NONVENDOR_LENGTH(len)
Definition nbi.c:57
#define NBI_VENDOR_LENGTH(len)
Definition nbi.c:58

Definition at line 59 of file nbi.c.

Referenced by nbi_process_segments().

◆ NBI_PROGRAM_RETURNS

#define NBI_PROGRAM_RETURNS ( flags)
Value:
( (flags) & ( 1U << 8 ) )
uint8_t flags
Flags.
Definition ena.h:7

Definition at line 62 of file nbi.c.

Referenced by nbi_exec().

◆ NBI_LINEAR_EXEC_ADDR

#define NBI_LINEAR_EXEC_ADDR ( flags)
Value:
( (flags) & ( 1U << 31 ) )

Definition at line 63 of file nbi.c.

Referenced by nbi_exec().

◆ NBI_HEADER_LENGTH

#define NBI_HEADER_LENGTH   512

NBI header length.

Definition at line 66 of file nbi.c.

Referenced by nbi_probe(), and nbi_process_segments().

◆ NBI_LOADADDR_FLAGS

#define NBI_LOADADDR_FLAGS ( flags)
Value:
( (flags) & 0x03 )

Definition at line 86 of file nbi.c.

Referenced by nbi_process_segments().

◆ NBI_LOADADDR_ABS

#define NBI_LOADADDR_ABS   0x00

Definition at line 87 of file nbi.c.

Referenced by nbi_process_segments().

◆ NBI_LOADADDR_AFTER

#define NBI_LOADADDR_AFTER   0x01

Definition at line 88 of file nbi.c.

Referenced by nbi_process_segments().

◆ NBI_LOADADDR_END

#define NBI_LOADADDR_END   0x02

Definition at line 89 of file nbi.c.

Referenced by nbi_process_segments().

◆ NBI_LOADADDR_BEFORE

#define NBI_LOADADDR_BEFORE   0x03

Definition at line 90 of file nbi.c.

Referenced by nbi_process_segments().

◆ NBI_LAST_SEGHEADER

#define NBI_LAST_SEGHEADER ( flags)
Value:
( (flags) & ( 1U << 2 ) )

Definition at line 91 of file nbi.c.

Referenced by nbi_process_segments().

Function Documentation

◆ FEATURE()

FEATURE ( FEATURE_IMAGE ,
"NBI" ,
DHCP_EB_FEATURE_NBI ,
1  )

◆ nbi_prepare_segment()

int nbi_prepare_segment ( struct image * image,
size_t offset __unused,
void * dest,
size_t filesz,
size_t memsz )
static

Prepare a segment for an NBI image.

Parameters
imageNBI image
offsetOffset within NBI image
fileszLength of initialised-data portion of the segment
memszTotal length of the segment
srcSource for initialised data
Return values
rcReturn status code

Definition at line 109 of file nbi.c.

110 {
111 int rc;
112
113 if ( ( rc = prep_segment ( dest, filesz, memsz ) ) != 0 ) {
114 DBGC ( image, "NBI %s could not prepare segment: %s\n",
115 image->name, strerror ( rc ) );
116 return rc;
117 }
118
119 return 0;
120}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
static size_t memsz
Definition fdtmem.c:51
#define DBGC(...)
Definition compiler.h:530
int prep_segment(void *segment, size_t filesz, size_t memsz)
Prepare segment for loading.
Definition segment.c:61
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An executable image.
Definition image.h:24
char * name
Name.
Definition image.h:38

References __unused, DBGC, dest, memsz, image::name, offset, prep_segment(), rc, and strerror().

Referenced by nbi_exec().

◆ nbi_load_segment()

int nbi_load_segment ( struct image * image,
size_t offset,
void * dest,
size_t filesz,
size_t memsz __unused )
static

Load a segment for an NBI image.

Parameters
imageNBI image
offsetOffset within NBI image
fileszLength of initialised-data portion of the segment
memszTotal length of the segment
srcSource for initialised data
Return values
rcReturn status code

Definition at line 132 of file nbi.c.

134 {
135 memcpy ( dest, ( image->data + offset ), filesz );
136 return 0;
137}
uint16_t offset
Offset to command line.
Definition bzimage.h:3
void * memcpy(void *dest, const void *src, size_t len) __nonnull
const void * data
Read-only data.
Definition image.h:51

References __unused, image::data, dest, memcpy(), memsz, and offset.

Referenced by nbi_exec().

◆ nbi_process_segments()

int nbi_process_segments ( struct image * image,
const struct imgheader * imgheader,
int(* process )(struct image *image, size_t offset, void *dest, size_t filesz, size_t memsz) )
static

Process segments of an NBI image.

Parameters
imageNBI image
imgheaderImage header information
processFunction to call for each segment
Return values
rcReturn status code

Definition at line 147 of file nbi.c.

153 {
154 const struct segheader *sh;
155 size_t offset = 0;
156 size_t sh_off;
157 void *dest;
158 size_t filesz;
159 size_t memsz;
160 int rc;
161
162 /* Copy image header to target location */
165 filesz = memsz = NBI_HEADER_LENGTH;
166 if ( ( rc = process ( image, offset, dest, filesz, memsz ) ) != 0 )
167 return rc;
168 offset += filesz;
169
170 /* Process segments in turn */
171 sh_off = NBI_LENGTH ( imgheader->length );
172 do {
173 /* Read segment header */
174 if ( ( sh_off + sizeof ( *sh ) ) > image->len ) {
175 DBGC ( image, "NBI %s segheader outside file\n",
176 image->name );
177 return -ENOEXEC;
178 }
179 sh = ( image->data + sh_off );
180 if ( sh->length == 0 ) {
181 /* Avoid infinite loop? */
182 DBGC ( image, "NBI %s invalid segheader length 0\n",
183 image->name );
184 return -ENOEXEC;
185 }
186
187 /* Calculate segment load address */
188 switch ( NBI_LOADADDR_FLAGS ( sh->flags ) ) {
189 case NBI_LOADADDR_ABS:
190 dest = phys_to_virt ( sh->loadaddr );
191 break;
193 dest = ( dest + memsz + sh->loadaddr );
194 break;
196 dest = ( dest - sh->loadaddr );
197 break;
198 case NBI_LOADADDR_END:
199 /* Not correct according to the spec, but
200 * maintains backwards compatibility with
201 * previous versions of Etherboot.
202 */
203 dest = phys_to_virt ( ( extmemsize() + 1024 ) * 1024
204 - sh->loadaddr );
205 break;
206 default:
207 /* Cannot be reached */
208 assert ( 0 );
209 }
210
211 /* Process this segment */
212 filesz = sh->imglength;
213 memsz = sh->memlength;
214 if ( ( offset > image->len ) ||
215 ( filesz > ( image->len - offset ) ) ) {
216 DBGC ( image, "NBI %s segment outside file\n",
217 image->name );
218 return -ENOEXEC;
219 }
220 if ( ( rc = process ( image, offset, dest,
221 filesz, memsz ) ) != 0 ) {
222 return rc;
223 }
224 offset += filesz;
225
226 /* Next segheader */
227 sh_off += NBI_LENGTH ( sh->length );
228 if ( sh_off >= NBI_HEADER_LENGTH ) {
229 DBGC ( image, "NBI %s header overflow\n",
230 image->name );
231 return -ENOEXEC;
232 }
233
234 } while ( ! NBI_LAST_SEGHEADER ( sh->flags ) );
235
236 if ( offset != image->len ) {
237 DBGC ( image, "NBI %s length wrong (file %zd, metadata %zd)\n",
238 image->name, image->len, offset );
239 return -ENOEXEC;
240 }
241
242 return 0;
243}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
#define ENOEXEC
Exec format error.
Definition errno.h:563
unsigned int extmemsize(void)
Get size of extended memory.
Definition int15.c:159
#define NBI_LAST_SEGHEADER(flags)
Definition nbi.c:91
#define NBI_HEADER_LENGTH
NBI header length.
Definition nbi.c:66
#define NBI_LOADADDR_BEFORE
Definition nbi.c:90
#define NBI_LOADADDR_ABS
Definition nbi.c:87
#define NBI_LOADADDR_FLAGS(flags)
Definition nbi.c:86
#define NBI_LOADADDR_AFTER
Definition nbi.c:88
#define NBI_LENGTH(len)
Definition nbi.c:59
#define NBI_LOADADDR_END
Definition nbi.c:89
static __always_inline void * real_to_virt(unsigned int segment, unsigned int offset)
Convert segment:offset address to virtual address.
Definition realmode.h:77
size_t len
Length of raw file image.
Definition image.h:63
An NBI image header.
Definition nbi.c:40
unsigned char length
Nibble-coded header length.
Definition nbi.c:43
segoff_t location
16-bit seg:off header location
Definition nbi.c:46
A process.
Definition process.h:18
An NBI segment header.
Definition nbi.c:75
unsigned char flags
Segment flags.
Definition nbi.c:79
unsigned long loadaddr
Load address.
Definition nbi.c:80
unsigned long memlength
Segment length in memory.
Definition nbi.c:82
unsigned long imglength
Segment length in NBI file.
Definition nbi.c:81
unsigned char length
Nibble-coded header length.
Definition nbi.c:76
uint16_t segment
Definition registers.h:193
uint16_t offset
Definition registers.h:192

References assert, image::data, DBGC, dest, ENOEXEC, extmemsize(), segheader::flags, segheader::imglength, image::len, imgheader::length, segheader::length, segheader::loadaddr, imgheader::location, segheader::memlength, memsz, image::name, NBI_HEADER_LENGTH, NBI_LAST_SEGHEADER, NBI_LENGTH, NBI_LOADADDR_ABS, NBI_LOADADDR_AFTER, NBI_LOADADDR_BEFORE, NBI_LOADADDR_END, NBI_LOADADDR_FLAGS, offset, segoff::offset, rc, real_to_virt(), and segoff::segment.

Referenced by nbi_exec().

◆ nbi_boot16()

int nbi_boot16 ( struct image * image,
const struct imgheader * imgheader )
static

Boot a 16-bit NBI image.

Parameters
imgheaderImage header information
Return values
rcReturn status code, if image returns

Definition at line 251 of file nbi.c.

252 {
253 int discard_D, discard_S, discard_b;
254 int32_t rc;
255
256 DBGC ( image, "NBI %s executing 16-bit image at %04x:%04x\n",
259
261 REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
262 "pushw %%ds\n\t" /* far pointer to bootp data */
263 "pushw %%bx\n\t"
264 "pushl %%esi\n\t" /* location */
265 "pushw %%cs\n\t" /* lcall execaddr */
266 "call 1f\n\t"
267 "jmp 2f\n\t"
268 "\n1:\n\t"
269 "pushl %%edi\n\t"
270 "lret\n\t"
271 "\n2:\n\t"
272 "addw $8,%%sp\n\t" /* clean up stack */
273 "popl %%ebp\n\t" /* gcc bug */ )
274 : "=a" ( rc ), "=D" ( discard_D ), "=S" ( discard_S ),
275 "=b" ( discard_b )
276 : "D" ( imgheader->execaddr.segoff ),
277 "S" ( imgheader->location ),
278 "b" ( __from_data16 ( basemem_packet ) )
279 : "ecx", "edx" );
280
281 return rc;
282}
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
signed int int32_t
Definition stdint.h:17
void * discard_D
Definition bigint.h:146
void * discard_S
Definition bigint.h:31
#define basemem_packet
#define REAL_CODE(asm_code_str)
Definition libkir.h:226
#define __from_data16(pointer)
Definition libkir.h:22
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
union imgheader::@012245212055350361152346201066323020337132126275 execaddr
segoff_t segoff
16-bit seg:off entry point
Definition nbi.c:48

References __asm__(), __from_data16, __volatile__(), basemem_packet, DBGC, discard_D, discard_S, imgheader::execaddr, imgheader::location, image::name, segoff::offset, rc, REAL_CODE, segoff::segment, and imgheader::segoff.

Referenced by nbi_exec().

◆ nbi_boot32()

int nbi_boot32 ( struct image * image,
const struct imgheader * imgheader )
static

Boot a 32-bit NBI image.

Parameters
imgheaderImage header information
Return values
rcReturn status code, if image returns

Definition at line 290 of file nbi.c.

291 {
292 struct ebinfo loaderinfo = {
294 0
295 };
296 int discard_D, discard_S, discard_b;
297 int32_t rc;
298
299 DBGC ( image, "NBI %s executing 32-bit image at %lx\n",
301
302 /* Jump to OS with flat physical addressing */
304 PHYS_CODE ( "pushl %%ebp\n\t" /* gcc bug */
305 "pushl %%ebx\n\t" /* bootp data */
306 "pushl %%esi\n\t" /* imgheader */
307 "pushl %%eax\n\t" /* loaderinfo */
308 "call *%%edi\n\t"
309 "addl $12, %%esp\n\t" /* clean up stack */
310 "popl %%ebp\n\t" /* gcc bug */ )
311 : "=a" ( rc ), "=D" ( discard_D ), "=S" ( discard_S ),
312 "=b" ( discard_b )
313 : "D" ( imgheader->execaddr.linear ),
314 "S" ( ( imgheader->location.segment << 4 ) +
316 "b" ( virt_to_phys ( basemem_packet ) ),
317 "a" ( virt_to_phys ( &loaderinfo ) )
318 : "ecx", "edx", "memory" );
319
320 return rc;
321}
#define PHYS_CODE(asm_code_str)
Definition librm.h:167
Definition nbi.c:94
unsigned long linear
32-bit entry point
Definition nbi.c:49
const int product_major_version
Product major version.
Definition version.c:66
const int product_minor_version
Product minor version.
Definition version.c:69

References __asm__(), __volatile__(), basemem_packet, DBGC, discard_D, discard_S, imgheader::execaddr, imgheader::linear, imgheader::location, image::name, segoff::offset, PHYS_CODE, product_major_version, product_minor_version, rc, and segoff::segment.

Referenced by nbi_exec().

◆ nbi_prepare_dhcp()

int nbi_prepare_dhcp ( struct image * image)
static

Prepare DHCP parameter block for NBI image.

Parameters
imageNBI image
Return values
rcReturn status code

Definition at line 329 of file nbi.c.

329 {
330 struct net_device *boot_netdev;
331 int rc;
332
333 boot_netdev = last_opened_netdev();
334 if ( ! boot_netdev ) {
335 DBGC ( image, "NBI %s could not identify a network device\n",
336 image->name );
337 return -ENODEV;
338 }
339
340 if ( ( rc = create_fakedhcpack ( boot_netdev, basemem_packet,
341 sizeof ( basemem_packet ) ) ) != 0 ) {
342 DBGC ( image, "NBI %s failed to build DHCP packet\n",
343 image->name );
344 return rc;
345 }
346
347 return 0;
348}
int create_fakedhcpack(struct net_device *netdev, void *data, size_t max_len)
Create fake DHCPACK packet.
Definition fakedhcp.c:137
#define ENODEV
No such device.
Definition errno.h:553
struct net_device * last_opened_netdev(void)
Get most recently opened network device.
Definition netdevice.c:1052
A network device.
Definition netdevice.h:353

References basemem_packet, create_fakedhcpack(), DBGC, ENODEV, last_opened_netdev(), image::name, and rc.

Referenced by nbi_exec().

◆ nbi_exec()

int nbi_exec ( struct image * image)
static

Execute a loaded NBI image.

Parameters
imageNBI image
Return values
rcReturn status code

Definition at line 356 of file nbi.c.

356 {
357 const struct imgheader *imgheader;
358 int may_return;
359 int rc;
360
361 /* Retrieve image header */
363
364 DBGC ( image, "NBI %s placing header at %hx:%hx\n", image->name,
366
367 /* NBI files can have overlaps between segments; the bss of
368 * one segment may overlap the initialised data of another. I
369 * assume this is a design flaw, but there are images out
370 * there that we need to work with. We therefore do two
371 * passes: first to initialise the segments, then to copy the
372 * data. This avoids zeroing out already-copied data.
373 */
375 nbi_prepare_segment ) ) != 0 )
376 return rc;
378 nbi_load_segment ) ) != 0 )
379 return rc;
380
381 /* Prepare DHCP option block */
382 if ( ( rc = nbi_prepare_dhcp ( image ) ) != 0 )
383 return rc;
384
385 /* Shut down now if NBI image will not return */
386 may_return = NBI_PROGRAM_RETURNS ( imgheader->flags );
387 if ( ! may_return )
389
390 /* Execute NBI image */
393 } else {
395 }
396
397 if ( ! may_return ) {
398 /* Cannot continue after shutdown() called */
399 DBGC ( image, "NBI %s returned %d from non-returnable image\n",
400 image->name, rc );
401 while ( 1 ) {}
402 }
403
404 DBGC ( image, "NBI %s returned %d\n", image->name, rc );
405
406 return rc;
407}
static void shutdown_boot(void)
Shut down system for OS boot.
Definition init.h:78
static int nbi_boot32(struct image *image, const struct imgheader *imgheader)
Boot a 32-bit NBI image.
Definition nbi.c:290
static int nbi_prepare_dhcp(struct image *image)
Prepare DHCP parameter block for NBI image.
Definition nbi.c:329
#define NBI_LINEAR_EXEC_ADDR(flags)
Definition nbi.c:63
static int nbi_prepare_segment(struct image *image, size_t offset __unused, void *dest, size_t filesz, size_t memsz)
Prepare a segment for an NBI image.
Definition nbi.c:109
static int nbi_boot16(struct image *image, const struct imgheader *imgheader)
Boot a 16-bit NBI image.
Definition nbi.c:251
static int nbi_process_segments(struct image *image, const struct imgheader *imgheader, int(*process)(struct image *image, size_t offset, void *dest, size_t filesz, size_t memsz))
Process segments of an NBI image.
Definition nbi.c:147
#define NBI_PROGRAM_RETURNS(flags)
Definition nbi.c:62
static int nbi_load_segment(struct image *image, size_t offset, void *dest, size_t filesz, size_t memsz __unused)
Load a segment for an NBI image.
Definition nbi.c:132
unsigned long flags
Image flags.
Definition nbi.c:44

References image::data, DBGC, imgheader::flags, imgheader::location, image::name, nbi_boot16(), nbi_boot32(), NBI_LINEAR_EXEC_ADDR, nbi_load_segment(), nbi_prepare_dhcp(), nbi_prepare_segment(), nbi_process_segments(), NBI_PROGRAM_RETURNS, segoff::offset, rc, segoff::segment, and shutdown_boot().

Referenced by __image_type().

◆ nbi_probe()

int nbi_probe ( struct image * image)
static

Probe NBI image.

Parameters
imageNBI image
Return values
rcReturn status code

Definition at line 415 of file nbi.c.

415 {
416 const struct imgheader *imgheader;
417
418 /* If we don't have enough data give up */
419 if ( image->len < NBI_HEADER_LENGTH ) {
420 DBGC ( image, "NBI %s too short for an NBI image\n",
421 image->name );
422 return -ENOEXEC;
423 }
425
426 /* Check image header */
427 if ( imgheader->magic != NBI_MAGIC ) {
428 DBGC ( image, "NBI %s has no NBI signature\n", image->name );
429 return -ENOEXEC;
430 }
431
432 return 0;
433}
#define NBI_MAGIC
NBI magic number.
Definition nbi.c:54
unsigned long magic
Magic number (NBI_MAGIC).
Definition nbi.c:41

References image::data, DBGC, ENOEXEC, image::len, imgheader::magic, image::name, NBI_HEADER_LENGTH, and NBI_MAGIC.

Referenced by __image_type().

◆ __image_type()

struct image_type nbi_image_type __image_type ( PROBE_NORMAL )

NBI image type.

References __image_type, nbi_exec(), nbi_probe(), and PROBE_NORMAL.