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) & ( 1 << 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) & ( 1 << 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) & ( 1 << 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:505
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 sh = ( image->data + sh_off );
175 if ( sh->length == 0 ) {
176 /* Avoid infinite loop? */
177 DBGC ( image, "NBI %s invalid segheader length 0\n",
178 image->name );
179 return -ENOEXEC;
180 }
181
182 /* Calculate segment load address */
183 switch ( NBI_LOADADDR_FLAGS ( sh->flags ) ) {
184 case NBI_LOADADDR_ABS:
185 dest = phys_to_virt ( sh->loadaddr );
186 break;
188 dest = ( dest + memsz + sh->loadaddr );
189 break;
191 dest = ( dest - sh->loadaddr );
192 break;
193 case NBI_LOADADDR_END:
194 /* Not correct according to the spec, but
195 * maintains backwards compatibility with
196 * previous versions of Etherboot.
197 */
198 dest = phys_to_virt ( ( extmemsize() + 1024 ) * 1024
199 - sh->loadaddr );
200 break;
201 default:
202 /* Cannot be reached */
203 assert ( 0 );
204 }
205
206 /* Process this segment */
207 filesz = sh->imglength;
208 memsz = sh->memlength;
209 if ( ( offset + filesz ) > image->len ) {
210 DBGC ( image, "NBI %s segment outside file\n",
211 image->name );
212 return -ENOEXEC;
213 }
214 if ( ( rc = process ( image, offset, dest,
215 filesz, memsz ) ) != 0 ) {
216 return rc;
217 }
218 offset += filesz;
219
220 /* Next segheader */
221 sh_off += NBI_LENGTH ( sh->length );
222 if ( sh_off >= NBI_HEADER_LENGTH ) {
223 DBGC ( image, "NBI %s header overflow\n",
224 image->name );
225 return -ENOEXEC;
226 }
227
228 } while ( ! NBI_LAST_SEGHEADER ( sh->flags ) );
229
230 if ( offset != image->len ) {
231 DBGC ( image, "NBI %s length wrong (file %zd, metadata %zd)\n",
232 image->name, image->len, offset );
233 return -ENOEXEC;
234 }
235
236 return 0;
237}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
#define ENOEXEC
Exec format error.
Definition errno.h:520
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:56
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 245 of file nbi.c.

246 {
247 int discard_D, discard_S, discard_b;
248 int32_t rc;
249
250 DBGC ( image, "NBI %s executing 16-bit image at %04x:%04x\n",
253
255 REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
256 "pushw %%ds\n\t" /* far pointer to bootp data */
257 "pushw %%bx\n\t"
258 "pushl %%esi\n\t" /* location */
259 "pushw %%cs\n\t" /* lcall execaddr */
260 "call 1f\n\t"
261 "jmp 2f\n\t"
262 "\n1:\n\t"
263 "pushl %%edi\n\t"
264 "lret\n\t"
265 "\n2:\n\t"
266 "addw $8,%%sp\n\t" /* clean up stack */
267 "popl %%ebp\n\t" /* gcc bug */ )
268 : "=a" ( rc ), "=D" ( discard_D ), "=S" ( discard_S ),
269 "=b" ( discard_b )
270 : "D" ( imgheader->execaddr.segoff ),
271 "S" ( imgheader->location ),
272 "b" ( __from_data16 ( basemem_packet ) )
273 : "ecx", "edx" );
274
275 return rc;
276}
__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:32
void * discard_S
Definition bigint.h:66
#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 284 of file nbi.c.

285 {
286 struct ebinfo loaderinfo = {
288 0
289 };
290 int discard_D, discard_S, discard_b;
291 int32_t rc;
292
293 DBGC ( image, "NBI %s executing 32-bit image at %lx\n",
295
296 /* Jump to OS with flat physical addressing */
298 PHYS_CODE ( "pushl %%ebp\n\t" /* gcc bug */
299 "pushl %%ebx\n\t" /* bootp data */
300 "pushl %%esi\n\t" /* imgheader */
301 "pushl %%eax\n\t" /* loaderinfo */
302 "call *%%edi\n\t"
303 "addl $12, %%esp\n\t" /* clean up stack */
304 "popl %%ebp\n\t" /* gcc bug */ )
305 : "=a" ( rc ), "=D" ( discard_D ), "=S" ( discard_S ),
306 "=b" ( discard_b )
307 : "D" ( imgheader->execaddr.linear ),
308 "S" ( ( imgheader->location.segment << 4 ) +
310 "b" ( virt_to_phys ( basemem_packet ) ),
311 "a" ( virt_to_phys ( &loaderinfo ) )
312 : "ecx", "edx", "memory" );
313
314 return rc;
315}
#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:65
const int product_minor_version
Product minor version.
Definition version.c:68

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 323 of file nbi.c.

323 {
324 struct net_device *boot_netdev;
325 int rc;
326
327 boot_netdev = last_opened_netdev();
328 if ( ! boot_netdev ) {
329 DBGC ( image, "NBI %s could not identify a network device\n",
330 image->name );
331 return -ENODEV;
332 }
333
334 if ( ( rc = create_fakedhcpack ( boot_netdev, basemem_packet,
335 sizeof ( basemem_packet ) ) ) != 0 ) {
336 DBGC ( image, "NBI %s failed to build DHCP packet\n",
337 image->name );
338 return rc;
339 }
340
341 return 0;
342}
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:510
struct net_device * last_opened_netdev(void)
Get most recently opened network device.
Definition netdevice.c:1048
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 350 of file nbi.c.

350 {
351 const struct imgheader *imgheader;
352 int may_return;
353 int rc;
354
355 /* Retrieve image header */
357
358 DBGC ( image, "NBI %s placing header at %hx:%hx\n", image->name,
360
361 /* NBI files can have overlaps between segments; the bss of
362 * one segment may overlap the initialised data of another. I
363 * assume this is a design flaw, but there are images out
364 * there that we need to work with. We therefore do two
365 * passes: first to initialise the segments, then to copy the
366 * data. This avoids zeroing out already-copied data.
367 */
369 nbi_prepare_segment ) ) != 0 )
370 return rc;
372 nbi_load_segment ) ) != 0 )
373 return rc;
374
375 /* Prepare DHCP option block */
376 if ( ( rc = nbi_prepare_dhcp ( image ) ) != 0 )
377 return rc;
378
379 /* Shut down now if NBI image will not return */
380 may_return = NBI_PROGRAM_RETURNS ( imgheader->flags );
381 if ( ! may_return )
383
384 /* Execute NBI image */
387 } else {
389 }
390
391 if ( ! may_return ) {
392 /* Cannot continue after shutdown() called */
393 DBGC ( image, "NBI %s returned %d from non-returnable image\n",
394 image->name, rc );
395 while ( 1 ) {}
396 }
397
398 DBGC ( image, "NBI %s returned %d\n", image->name, rc );
399
400 return rc;
401}
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:284
static int nbi_prepare_dhcp(struct image *image)
Prepare DHCP parameter block for NBI image.
Definition nbi.c:323
#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:245
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 409 of file nbi.c.

409 {
410 const struct imgheader *imgheader;
411
412 /* If we don't have enough data give up */
413 if ( image->len < NBI_HEADER_LENGTH ) {
414 DBGC ( image, "NBI %s too short for an NBI image\n",
415 image->name );
416 return -ENOEXEC;
417 }
419
420 /* Check image header */
421 if ( imgheader->magic != NBI_MAGIC ) {
422 DBGC ( image, "NBI %s has no NBI signature\n", image->name );
423 return -ENOEXEC;
424 }
425
426 return 0;
427}
#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.