Dead code removal.
Kill off use of etherboot.h outside drivers/net.
This commit is contained in:
parent
95c07736cb
commit
e330db3c74
|
@ -7,9 +7,9 @@
|
||||||
* your option) any later version.
|
* your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "etherboot.h"
|
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "latch.h"
|
#include "latch.h"
|
||||||
|
#include <io.h>
|
||||||
#include <gpxe/init.h>
|
#include <gpxe/init.h>
|
||||||
|
|
||||||
void __load_timer2(unsigned int ticks)
|
void __load_timer2(unsigned int ticks)
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
* move to Etherboot by LYH
|
* move to Etherboot by LYH
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "etherboot.h"
|
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include <gpxe/init.h>
|
#include <gpxe/init.h>
|
||||||
#include <gpxe/pci.h>
|
#include <gpxe/pci.h>
|
||||||
|
|
|
@ -5,10 +5,6 @@
|
||||||
* your option) any later version.
|
* your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "etherboot.h"
|
|
||||||
#include "dev.h"
|
|
||||||
#include "console.h"
|
|
||||||
|
|
||||||
#include "config/general.h"
|
#include "config/general.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
176
src/core/dev.c
176
src/core/dev.c
|
@ -1,176 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <etherboot.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <dev.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Each bus driver defines several methods, which are described in
|
|
||||||
* dev.h. This file provides a centralised, bus-independent mechanism
|
|
||||||
* for locating devices and drivers.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Linker symbols for the various tables */
|
|
||||||
static struct bus_driver bus_drivers[0]
|
|
||||||
__table_start ( struct bus_driver, bus_driver );
|
|
||||||
static struct bus_driver bus_drivers_end[0]
|
|
||||||
__table_end ( struct bus_driver, bus_driver );
|
|
||||||
static struct device_driver device_drivers[0]
|
|
||||||
__table_start ( struct device_driver, device_driver );
|
|
||||||
static struct device_driver device_drivers_end[0]
|
|
||||||
__table_end ( struct device_driver, device_driver );
|
|
||||||
|
|
||||||
/* Current attempted boot device */
|
|
||||||
struct dev dev = {
|
|
||||||
.bus_driver = bus_drivers,
|
|
||||||
.device_driver = device_drivers,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print all drivers
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void print_drivers ( void ) {
|
|
||||||
struct device_driver *driver;
|
|
||||||
|
|
||||||
for ( driver = device_drivers ;
|
|
||||||
driver < device_drivers_end ;
|
|
||||||
driver++ ) {
|
|
||||||
printf ( "%s ", driver->name );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Move to the next location on any bus
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static inline int next_location ( struct bus_driver **bus_driver,
|
|
||||||
struct bus_loc *bus_loc ) {
|
|
||||||
/* Move to next location on this bus, if any */
|
|
||||||
if ( (*bus_driver)->next_location ( bus_loc ) )
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Move to first (zeroed) location on next bus, if any */
|
|
||||||
if ( ++(*bus_driver) < bus_drivers_end ) {
|
|
||||||
DBG ( "DEV scanning %s bus\n", (*bus_driver)->name );
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset to first bus, return "no more locations" */
|
|
||||||
*bus_driver = bus_drivers;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the next available device on any bus
|
|
||||||
*
|
|
||||||
* Set skip=1 to skip over the current device
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int find_any ( struct bus_driver **bus_driver, struct bus_loc *bus_loc,
|
|
||||||
struct bus_dev *bus_dev, signed int skip ) {
|
|
||||||
DBG ( "DEV scanning %s bus\n", (*bus_driver)->name );
|
|
||||||
do {
|
|
||||||
if ( --skip >= 0 )
|
|
||||||
continue;
|
|
||||||
if ( ! (*bus_driver)->fill_device ( bus_dev, bus_loc ) )
|
|
||||||
continue;
|
|
||||||
DBG ( "DEV found device %s\n",
|
|
||||||
(*bus_driver)->describe_device ( bus_dev ) );
|
|
||||||
return 1;
|
|
||||||
} while ( next_location ( bus_driver, bus_loc ) );
|
|
||||||
|
|
||||||
DBG ( "DEV found no more devices\n" );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find a driver by specified device.
|
|
||||||
*
|
|
||||||
* Set skip=1 to skip over the current driver
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int find_by_device ( struct device_driver **device_driver,
|
|
||||||
struct bus_driver *bus_driver, struct bus_dev *bus_dev,
|
|
||||||
signed int skip ) {
|
|
||||||
do {
|
|
||||||
if ( --skip >= 0 )
|
|
||||||
continue;
|
|
||||||
if ( (*device_driver)->bus_driver != bus_driver )
|
|
||||||
continue;
|
|
||||||
if ( ! bus_driver->check_driver ( bus_dev, *device_driver ))
|
|
||||||
continue;
|
|
||||||
DBG ( "DEV found driver %s for device %s\n",
|
|
||||||
(*device_driver)->name,
|
|
||||||
bus_driver->describe_device ( bus_dev ) );
|
|
||||||
return 1;
|
|
||||||
} while ( ++(*device_driver) < device_drivers_end );
|
|
||||||
|
|
||||||
/* Reset to first driver, return "not found" */
|
|
||||||
DBG ( "DEV found no driver for device %s\n",
|
|
||||||
bus_driver->describe_device ( bus_dev ) );
|
|
||||||
*device_driver = device_drivers;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find a device by specified driver.
|
|
||||||
*
|
|
||||||
* Set skip=1 to skip over the current device
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int find_by_driver ( struct bus_loc *bus_loc, struct bus_dev *bus_dev,
|
|
||||||
struct device_driver *device_driver,
|
|
||||||
signed int skip ) {
|
|
||||||
struct bus_driver *bus_driver = device_driver->bus_driver;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if ( --skip >= 0 )
|
|
||||||
continue;
|
|
||||||
if ( ! bus_driver->fill_device ( bus_dev, bus_loc ) )
|
|
||||||
continue;
|
|
||||||
if ( ! bus_driver->check_driver ( bus_dev, device_driver ) )
|
|
||||||
continue;
|
|
||||||
DBG ( "DEV found device %s for driver %s\n",
|
|
||||||
bus_driver->describe_device ( bus_dev ),
|
|
||||||
device_driver->name );
|
|
||||||
return 1;
|
|
||||||
} while ( bus_driver->next_location ( bus_loc ) );
|
|
||||||
|
|
||||||
DBG ( "DEV found no device for driver %s\n", device_driver->name );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the next available (device,driver) combination
|
|
||||||
*
|
|
||||||
* Set skip=1 to skip over the current (device,driver)
|
|
||||||
*
|
|
||||||
* Note that the struct dev may not have been previously used, and so
|
|
||||||
* may not contain a valid (device,driver) combination.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int find_any_with_driver ( struct dev *dev, signed int skip ) {
|
|
||||||
signed int skip_device = 0;
|
|
||||||
signed int skip_driver = skip;
|
|
||||||
|
|
||||||
while ( find_any ( &dev->bus_driver, &dev->bus_loc, &dev->bus_dev,
|
|
||||||
skip_device ) ) {
|
|
||||||
if ( find_by_device ( &dev->device_driver, dev->bus_driver,
|
|
||||||
&dev->bus_dev, skip_driver ) ) {
|
|
||||||
/* Set type_driver to be that of the device
|
|
||||||
* driver
|
|
||||||
*/
|
|
||||||
dev->type_driver = dev->device_driver->type_driver;
|
|
||||||
/* Set type device instance to be the single
|
|
||||||
* instance provided by the type driver
|
|
||||||
*/
|
|
||||||
dev->type_dev = dev->type_driver->type_dev;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
skip_driver = 0;
|
|
||||||
skip_device = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,699 +0,0 @@
|
||||||
#include "elf.h"
|
|
||||||
|
|
||||||
#ifndef ELF_CHECK_ARCH
|
|
||||||
#error ELF_CHECK_ARCH not defined
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ELF_NOTES 1
|
|
||||||
#define ELF_DEBUG 0
|
|
||||||
|
|
||||||
struct elf_state
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
Elf32_Ehdr elf32;
|
|
||||||
Elf64_Ehdr elf64;
|
|
||||||
} e;
|
|
||||||
union {
|
|
||||||
Elf32_Phdr phdr32[1];
|
|
||||||
Elf64_Phdr phdr64[1];
|
|
||||||
unsigned char dummy[1024];
|
|
||||||
} p;
|
|
||||||
unsigned long curaddr;
|
|
||||||
int segment; /* current segment number, -1 for none */
|
|
||||||
uint64_t loc; /* start offset of current block */
|
|
||||||
uint64_t skip; /* padding to be skipped to current segment */
|
|
||||||
unsigned long toread; /* remaining data to be read in the segment */
|
|
||||||
#if ELF_NOTES
|
|
||||||
int check_ip_checksum;
|
|
||||||
uint16_t ip_checksum;
|
|
||||||
unsigned long ip_checksum_offset;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct elf_state estate;
|
|
||||||
|
|
||||||
static unsigned long find_segment(unsigned long size, unsigned long align)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
/* Verify I have a power of 2 alignment */
|
|
||||||
if (align & (align - 1)) {
|
|
||||||
return ULONG_MAX;
|
|
||||||
}
|
|
||||||
for(i = 0; i < meminfo.map_count; i++) {
|
|
||||||
unsigned long r_start, r_end;
|
|
||||||
if (meminfo.map[i].type != E820_RAM)
|
|
||||||
continue;
|
|
||||||
if ((meminfo.map[i].addr + meminfo.map[i].size) > ULONG_MAX) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
r_start = meminfo.map[i].addr;
|
|
||||||
r_end = r_start + meminfo.map[i].size;
|
|
||||||
/* Don't allow the segment to overlap etherboot */
|
|
||||||
if ((r_end > virt_to_phys(_text)) && (r_start < virt_to_phys(_text))) {
|
|
||||||
r_end = virt_to_phys(_text);
|
|
||||||
}
|
|
||||||
if ((r_start > virt_to_phys(_text)) && (r_start < virt_to_phys(_end))) {
|
|
||||||
r_start = virt_to_phys(_end);
|
|
||||||
}
|
|
||||||
/* Don't allow the segment to overlap the heap */
|
|
||||||
if ((r_end > heap_ptr) && (r_start < heap_ptr)) {
|
|
||||||
r_end = heap_ptr;
|
|
||||||
}
|
|
||||||
if ((r_start > heap_ptr) && (r_start < heap_bot)) {
|
|
||||||
r_start = heap_ptr;
|
|
||||||
}
|
|
||||||
r_start = (r_start + align - 1) & ~(align - 1);
|
|
||||||
if ((r_end >= r_start) && ((r_end - r_start) >= size)) {
|
|
||||||
return r_start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* I did not find anything :( */
|
|
||||||
return ULONG_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void elf_boot(unsigned long machine, unsigned long entry)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
struct Elf_Bhdr *hdr;
|
|
||||||
multiboot_boot(entry);
|
|
||||||
/* We cleanup unconditionally, and then reawaken the network
|
|
||||||
* adapter after the longjmp.
|
|
||||||
*/
|
|
||||||
hdr = prepare_boot_params(&estate.e);
|
|
||||||
result = elf_start(machine, entry, virt_to_phys(hdr));
|
|
||||||
if (result == 0) {
|
|
||||||
result = -1;
|
|
||||||
}
|
|
||||||
printf("Secondary program returned %d\n", result);
|
|
||||||
longjmp(restart_etherboot, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ELF_NOTES
|
|
||||||
static int elf_prep_segment(
|
|
||||||
unsigned long start __unused, unsigned long mid __unused, unsigned long end __unused,
|
|
||||||
unsigned long istart, unsigned long iend)
|
|
||||||
|
|
||||||
{
|
|
||||||
if (estate.check_ip_checksum) {
|
|
||||||
if ((istart <= estate.ip_checksum_offset) &&
|
|
||||||
(iend > estate.ip_checksum_offset)) {
|
|
||||||
/* The checksum note is also loaded in a
|
|
||||||
* PT_LOAD segment, so the computed checksum
|
|
||||||
* should be 0.
|
|
||||||
*/
|
|
||||||
estate.ip_checksum = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define elf_prep_segment(start, mid, end, istart, iend) (1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if ELF_NOTES
|
|
||||||
static void process_elf_notes(unsigned char *header,
|
|
||||||
unsigned long offset, unsigned long length)
|
|
||||||
{
|
|
||||||
unsigned char *note, *end;
|
|
||||||
char *program, *version;
|
|
||||||
|
|
||||||
estate.check_ip_checksum = 0;
|
|
||||||
note = header + offset;
|
|
||||||
end = note + length;
|
|
||||||
program = version = 0;
|
|
||||||
while(note < end) {
|
|
||||||
Elf_Nhdr *hdr;
|
|
||||||
unsigned char *n_name, *n_desc, *next;
|
|
||||||
hdr = (Elf_Nhdr *)note;
|
|
||||||
n_name = note + sizeof(*hdr);
|
|
||||||
n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
|
|
||||||
next = n_desc + ((hdr->n_descsz + 3) & ~3);
|
|
||||||
if (next > end) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((hdr->n_namesz == sizeof(ELF_NOTE_BOOT)) &&
|
|
||||||
(memcmp(n_name, ELF_NOTE_BOOT, sizeof(ELF_NOTE_BOOT)) == 0)) {
|
|
||||||
switch(hdr->n_type) {
|
|
||||||
case EIN_PROGRAM_NAME:
|
|
||||||
if (n_desc[hdr->n_descsz -1] == 0) {
|
|
||||||
program = n_desc;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EIN_PROGRAM_VERSION:
|
|
||||||
if (n_desc[hdr->n_descsz -1] == 0) {
|
|
||||||
version = n_desc;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EIN_PROGRAM_CHECKSUM:
|
|
||||||
estate.check_ip_checksum = 1;
|
|
||||||
estate.ip_checksum = *((uint16_t *)n_desc);
|
|
||||||
/* Remember where the segment is so
|
|
||||||
* I can detect segment overlaps.
|
|
||||||
*/
|
|
||||||
estate.ip_checksum_offset = n_desc - header;
|
|
||||||
#if ELF_DEBUG
|
|
||||||
printf("Checksum: %hx\n", estate.ip_checksum);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if ELF_DEBUG
|
|
||||||
printf("n_type: %x n_name(%d): %s n_desc(%d): %s\n",
|
|
||||||
hdr->n_type,
|
|
||||||
hdr->n_namesz, n_name,
|
|
||||||
hdr->n_descsz, n_desc);
|
|
||||||
#endif
|
|
||||||
note = next;
|
|
||||||
}
|
|
||||||
if (program && version) {
|
|
||||||
printf("\nLoading %s version: %s\n", program, version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ELF_IMAGE
|
|
||||||
static sector_t elf32_download(unsigned char *data, unsigned int len, int eof);
|
|
||||||
static inline os_download_t elf32_probe(unsigned char *data, unsigned int len)
|
|
||||||
{
|
|
||||||
unsigned long phdr_size;
|
|
||||||
if (len < sizeof(estate.e.elf32)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
memcpy(&estate.e.elf32, data, sizeof(estate.e.elf32));
|
|
||||||
if ((estate.e.elf32.e_ident[EI_MAG0] != ELFMAG0) ||
|
|
||||||
(estate.e.elf32.e_ident[EI_MAG1] != ELFMAG1) ||
|
|
||||||
(estate.e.elf32.e_ident[EI_MAG2] != ELFMAG2) ||
|
|
||||||
(estate.e.elf32.e_ident[EI_MAG3] != ELFMAG3) ||
|
|
||||||
(estate.e.elf32.e_ident[EI_CLASS] != ELFCLASS32) ||
|
|
||||||
(estate.e.elf32.e_ident[EI_DATA] != ELFDATA_CURRENT) ||
|
|
||||||
(estate.e.elf32.e_ident[EI_VERSION] != EV_CURRENT) ||
|
|
||||||
( (estate.e.elf32.e_type != ET_EXEC) &&
|
|
||||||
(estate.e.elf32.e_type != ET_DYN)) ||
|
|
||||||
(estate.e.elf32.e_version != EV_CURRENT) ||
|
|
||||||
(estate.e.elf32.e_ehsize != sizeof(Elf32_Ehdr)) ||
|
|
||||||
(estate.e.elf32.e_phentsize != sizeof(Elf32_Phdr)) ||
|
|
||||||
!ELF_CHECK_ARCH(estate.e.elf32)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
printf("(ELF");
|
|
||||||
elf_freebsd_probe();
|
|
||||||
printf(")... ");
|
|
||||||
phdr_size = estate.e.elf32.e_phnum * estate.e.elf32.e_phentsize;
|
|
||||||
if (estate.e.elf32.e_phoff + phdr_size > len) {
|
|
||||||
printf("ELF header outside first block\n");
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
if (phdr_size > sizeof(estate.p.dummy)) {
|
|
||||||
printf("Program header too big\n");
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
memcpy(&estate.p.phdr32, data + estate.e.elf32.e_phoff, phdr_size);
|
|
||||||
if (estate.e.elf32.e_type == ET_DYN) {
|
|
||||||
Elf32_Addr min, max, base_addr, delta, align;
|
|
||||||
min = -1;
|
|
||||||
max = 0;
|
|
||||||
align = 1;
|
|
||||||
for(estate.segment = 0; estate.segment < estate.e.elf32.e_phnum; estate.segment++) {
|
|
||||||
Elf32_Addr val;
|
|
||||||
if (estate.p.phdr32[estate.segment].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
val = estate.p.phdr32[estate.segment].p_paddr;
|
|
||||||
if (val < min) {
|
|
||||||
min = val;
|
|
||||||
}
|
|
||||||
val += estate.p.phdr32[estate.segment].p_memsz;
|
|
||||||
if (val > max) {
|
|
||||||
max = val;
|
|
||||||
}
|
|
||||||
if (estate.p.phdr32[estate.segment].p_align > align) {
|
|
||||||
align = estate.p.phdr32[estate.segment].p_align;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (align & (align -1)) {
|
|
||||||
printf("ELF base address alignment is not a power of 2\n");
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
base_addr = find_segment(max - min, align);
|
|
||||||
if (base_addr == ULONG_MAX) {
|
|
||||||
printf("ELF base address not available for size %ld\n", max - min);
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
/* Compute the change in base address and fix up the addresses */
|
|
||||||
delta = base_addr - min;
|
|
||||||
for(estate.segment = 0; estate.segment < estate.e.elf32.e_phnum; estate.segment++) {
|
|
||||||
/* Change the base address of the object to load */
|
|
||||||
estate.p.phdr32[estate.segment].p_paddr += delta;
|
|
||||||
}
|
|
||||||
estate.e.elf32.e_entry += delta;
|
|
||||||
}
|
|
||||||
#if ELF_NOTES
|
|
||||||
/* Load ELF notes from the image */
|
|
||||||
estate.check_ip_checksum = 0;
|
|
||||||
for(estate.segment = 0; estate.segment < estate.e.elf32.e_phnum; estate.segment++) {
|
|
||||||
if (estate.p.phdr32[estate.segment].p_type != PT_NOTE)
|
|
||||||
continue;
|
|
||||||
if (estate.p.phdr32[estate.segment].p_offset + estate.p.phdr32[estate.segment].p_filesz > len) {
|
|
||||||
/* Ignore ELF notes outside of the first block */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
process_elf_notes(data,
|
|
||||||
estate.p.phdr32[estate.segment].p_offset, estate.p.phdr32[estate.segment].p_filesz);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* Check for Etherboot related limitations. Memory
|
|
||||||
* between _text and _end is not allowed.
|
|
||||||
* Reasons: the Etherboot code/data area.
|
|
||||||
*/
|
|
||||||
for (estate.segment = 0; estate.segment < estate.e.elf32.e_phnum; estate.segment++) {
|
|
||||||
unsigned long start, mid, end, istart, iend;
|
|
||||||
if (estate.p.phdr32[estate.segment].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
elf_freebsd_fixup_segment();
|
|
||||||
|
|
||||||
start = estate.p.phdr32[estate.segment].p_paddr;
|
|
||||||
mid = start + estate.p.phdr32[estate.segment].p_filesz;
|
|
||||||
end = start + estate.p.phdr32[estate.segment].p_memsz;
|
|
||||||
istart = estate.p.phdr32[estate.segment].p_offset;
|
|
||||||
iend = istart + estate.p.phdr32[estate.segment].p_filesz;
|
|
||||||
if (!prep_segment(start, mid, end, istart, iend)) {
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
if (!elf_prep_segment(start, mid, end, istart, iend)) {
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
estate.segment = -1;
|
|
||||||
estate.loc = 0;
|
|
||||||
estate.skip = 0;
|
|
||||||
estate.toread = 0;
|
|
||||||
multiboot_init();
|
|
||||||
return elf32_download;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sector_t elf32_download(unsigned char *data, unsigned int len, int eof)
|
|
||||||
{
|
|
||||||
unsigned long skip_sectors = 0;
|
|
||||||
unsigned int offset; /* working offset in the current data block */
|
|
||||||
int i;
|
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
do {
|
|
||||||
if (estate.segment != -1) {
|
|
||||||
if (estate.skip) {
|
|
||||||
if (estate.skip >= len - offset) {
|
|
||||||
estate.skip -= len - offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
offset += estate.skip;
|
|
||||||
estate.skip = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (estate.toread) {
|
|
||||||
unsigned int cplen;
|
|
||||||
cplen = len - offset;
|
|
||||||
if (cplen >= estate.toread) {
|
|
||||||
cplen = estate.toread;
|
|
||||||
}
|
|
||||||
memcpy(phys_to_virt(estate.curaddr), data+offset, cplen);
|
|
||||||
estate.curaddr += cplen;
|
|
||||||
estate.toread -= cplen;
|
|
||||||
offset += cplen;
|
|
||||||
if (estate.toread)
|
|
||||||
break;
|
|
||||||
elf_freebsd_find_segment_end();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Data left, but current segment finished - look for the next
|
|
||||||
* segment (in file offset order) that needs to be loaded.
|
|
||||||
* We can only seek forward, so select the program headers,
|
|
||||||
* in the correct order.
|
|
||||||
*/
|
|
||||||
estate.segment = -1;
|
|
||||||
for (i = 0; i < estate.e.elf32.e_phnum; i++) {
|
|
||||||
if (estate.p.phdr32[i].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
if (estate.p.phdr32[i].p_filesz == 0)
|
|
||||||
continue;
|
|
||||||
if (estate.p.phdr32[i].p_offset < estate.loc + offset)
|
|
||||||
continue; /* can't go backwards */
|
|
||||||
if ((estate.segment != -1) &&
|
|
||||||
(estate.p.phdr32[i].p_offset >= estate.p.phdr32[estate.segment].p_offset))
|
|
||||||
continue; /* search minimum file offset */
|
|
||||||
estate.segment = i;
|
|
||||||
}
|
|
||||||
if (estate.segment == -1) {
|
|
||||||
if (elf_freebsd_debug_loader(offset)) {
|
|
||||||
estate.segment = 0; /* -1 makes it not read anymore */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* No more segments to be loaded, so just start the
|
|
||||||
* kernel. This saves a lot of network bandwidth if
|
|
||||||
* debug info is in the kernel but not loaded. */
|
|
||||||
goto elf_startkernel;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
estate.curaddr = estate.p.phdr32[estate.segment].p_paddr;
|
|
||||||
estate.skip = estate.p.phdr32[estate.segment].p_offset - (estate.loc + offset);
|
|
||||||
estate.toread = estate.p.phdr32[estate.segment].p_filesz;
|
|
||||||
#if ELF_DEBUG
|
|
||||||
printf("PHDR %d, size %#lX, curaddr %#lX\n",
|
|
||||||
estate.segment, estate.toread, estate.curaddr);
|
|
||||||
#endif
|
|
||||||
} while (offset < len);
|
|
||||||
|
|
||||||
estate.loc += len + (estate.skip & ~0x1ff);
|
|
||||||
skip_sectors = estate.skip >> 9;
|
|
||||||
estate.skip &= 0x1ff;
|
|
||||||
|
|
||||||
if (eof) {
|
|
||||||
unsigned long entry;
|
|
||||||
unsigned long machine;
|
|
||||||
elf_startkernel:
|
|
||||||
entry = estate.e.elf32.e_entry;
|
|
||||||
machine = estate.e.elf32.e_machine;
|
|
||||||
|
|
||||||
#if ELF_NOTES
|
|
||||||
if (estate.check_ip_checksum) {
|
|
||||||
unsigned long bytes = 0;
|
|
||||||
uint16_t sum, new_sum;
|
|
||||||
|
|
||||||
sum = ipchksum(&estate.e.elf32, sizeof(estate.e.elf32));
|
|
||||||
bytes = sizeof(estate.e.elf32);
|
|
||||||
#if ELF_DEBUG
|
|
||||||
printf("Ehdr: %hx %hx sz: %lx bytes: %lx\n",
|
|
||||||
sum, sum, bytes, bytes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
new_sum = ipchksum(estate.p.phdr32, sizeof(estate.p.phdr32[0]) * estate.e.elf32.e_phnum);
|
|
||||||
sum = add_ipchksums(bytes, sum, new_sum);
|
|
||||||
bytes += sizeof(estate.p.phdr32[0]) * estate.e.elf32.e_phnum;
|
|
||||||
#if ELF_DEBUG
|
|
||||||
printf("Phdr: %hx %hx sz: %lx bytes: %lx\n",
|
|
||||||
new_sum, sum,
|
|
||||||
sizeof(estate.p.phdr32[0]) * estate.e.elf32.e_phnum, bytes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for(i = 0; i < estate.e.elf32.e_phnum; i++) {
|
|
||||||
if (estate.p.phdr32[i].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
new_sum = ipchksum(phys_to_virt(estate.p.phdr32[i].p_paddr),
|
|
||||||
estate.p.phdr32[i].p_memsz);
|
|
||||||
sum = add_ipchksums(bytes, sum, new_sum);
|
|
||||||
bytes += estate.p.phdr32[i].p_memsz;
|
|
||||||
#if ELF_DEBUG
|
|
||||||
printf("seg%d: %hx %hx sz: %x bytes: %lx\n",
|
|
||||||
i, new_sum, sum,
|
|
||||||
estate.p.phdr32[i].p_memsz, bytes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
if (estate.ip_checksum != sum) {
|
|
||||||
printf("\nImage checksum: %hx != computed checksum: %hx\n",
|
|
||||||
estate.ip_checksum, sum);
|
|
||||||
longjmp(restart_etherboot, -2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
done(1);
|
|
||||||
/* Fixup the offset to the program header so you can find the program headers from
|
|
||||||
* the ELF header mknbi needs this.
|
|
||||||
*/
|
|
||||||
estate.e.elf32.e_phoff = (char *)&estate.p - (char *)&estate.e;
|
|
||||||
elf_freebsd_boot(entry);
|
|
||||||
elf_boot(machine,entry);
|
|
||||||
}
|
|
||||||
return skip_sectors;
|
|
||||||
}
|
|
||||||
#endif /* ELF_IMAGE */
|
|
||||||
|
|
||||||
#ifdef ELF64_IMAGE
|
|
||||||
static sector_t elf64_download(unsigned char *data, unsigned int len, int eof);
|
|
||||||
static inline os_download_t elf64_probe(unsigned char *data, unsigned int len)
|
|
||||||
{
|
|
||||||
unsigned long phdr_size;
|
|
||||||
if (len < sizeof(estate.e.elf64)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
memcpy(&estate.e.elf64, data, sizeof(estate.e.elf64));
|
|
||||||
if ((estate.e.elf64.e_ident[EI_MAG0] != ELFMAG0) ||
|
|
||||||
(estate.e.elf64.e_ident[EI_MAG1] != ELFMAG1) ||
|
|
||||||
(estate.e.elf64.e_ident[EI_MAG2] != ELFMAG2) ||
|
|
||||||
(estate.e.elf64.e_ident[EI_MAG3] != ELFMAG3) ||
|
|
||||||
(estate.e.elf64.e_ident[EI_CLASS] != ELFCLASS64) ||
|
|
||||||
(estate.e.elf64.e_ident[EI_DATA] != ELFDATA_CURRENT) ||
|
|
||||||
(estate.e.elf64.e_ident[EI_VERSION] != EV_CURRENT) ||
|
|
||||||
( (estate.e.elf64.e_type != ET_EXEC) &&
|
|
||||||
(estate.e.elf64.e_type != ET_DYN)) ||
|
|
||||||
(estate.e.elf64.e_version != EV_CURRENT) ||
|
|
||||||
(estate.e.elf64.e_ehsize != sizeof(Elf64_Ehdr)) ||
|
|
||||||
(estate.e.elf64.e_phentsize != sizeof(Elf64_Phdr)) ||
|
|
||||||
!ELF_CHECK_ARCH(estate.e.elf64)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
printf("(ELF64)... ");
|
|
||||||
phdr_size = estate.e.elf64.e_phnum * estate.e.elf64.e_phentsize;
|
|
||||||
if (estate.e.elf64.e_phoff + phdr_size > len) {
|
|
||||||
printf("ELF header outside first block\n");
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
if (phdr_size > sizeof(estate.p.dummy)) {
|
|
||||||
printf("Program header to big\n");
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
if (estate.e.elf64.e_entry > ULONG_MAX) {
|
|
||||||
printf("ELF entry point exceeds address space\n");
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
memcpy(&estate.p.phdr64, data + estate.e.elf64.e_phoff, phdr_size);
|
|
||||||
if (estate.e.elf64.e_type == ET_DYN) {
|
|
||||||
Elf64_Addr min, max, base_addr, delta, align;
|
|
||||||
min = -1;
|
|
||||||
max = 0;
|
|
||||||
align = 1;
|
|
||||||
for(estate.segment = 0; estate.segment < estate.e.elf64.e_phnum; estate.segment++) {
|
|
||||||
Elf64_Addr val;
|
|
||||||
if (estate.p.phdr64[estate.segment].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
val = estate.p.phdr64[estate.segment].p_paddr;
|
|
||||||
if (val < min) {
|
|
||||||
min = val;
|
|
||||||
}
|
|
||||||
val += estate.p.phdr64[estate.segment].p_memsz;
|
|
||||||
if (val > max) {
|
|
||||||
max = val;
|
|
||||||
}
|
|
||||||
if (estate.p.phdr64[estate.segment].p_align > align) {
|
|
||||||
align = estate.p.phdr64[estate.segment].p_align;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (align > ULONG_MAX) {
|
|
||||||
printf("ELF base address alignment exceeds address space\n");
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
if (align & (align -1)) {
|
|
||||||
printf("ELF base address alignment is not a power of 2\n");
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
if ((max - min) > ULONG_MAX) {
|
|
||||||
printf("ELF size exceeds address space\n");
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
base_addr = find_segment(max - min, align);
|
|
||||||
if (base_addr == ULONG_MAX) {
|
|
||||||
printf("ELF base address not available for size %ld\n", max - min);
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
/* Compute the change in base address and fix up the addresses */
|
|
||||||
delta = base_addr - min;
|
|
||||||
for(estate.segment = 0; estate.segment < estate.e.elf64.e_phnum; estate.segment++) {
|
|
||||||
/* Change the base address of the object to load */
|
|
||||||
estate.p.phdr64[estate.segment].p_paddr += delta;
|
|
||||||
}
|
|
||||||
estate.e.elf64.e_entry += delta;
|
|
||||||
}
|
|
||||||
#if ELF_NOTES
|
|
||||||
/* Load ELF notes from the image */
|
|
||||||
estate.check_ip_checksum = 0;
|
|
||||||
for(estate.segment = 0; estate.segment < estate.e.elf64.e_phnum; estate.segment++) {
|
|
||||||
if (estate.p.phdr64[estate.segment].p_type != PT_NOTE)
|
|
||||||
continue;
|
|
||||||
if (estate.p.phdr64[estate.segment].p_offset + estate.p.phdr64[estate.segment].p_filesz > len) {
|
|
||||||
/* Ignore ELF notes outside of the first block */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
process_elf_notes(data,
|
|
||||||
estate.p.phdr64[estate.segment].p_offset, estate.p.phdr64[estate.segment].p_filesz);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* Check for Etherboot related limitations. Memory
|
|
||||||
* between _text and _end is not allowed.
|
|
||||||
* Reasons: the Etherboot code/data area.
|
|
||||||
*/
|
|
||||||
for (estate.segment = 0; estate.segment < estate.e.elf64.e_phnum; estate.segment++) {
|
|
||||||
unsigned long start, mid, end, istart, iend;
|
|
||||||
if (estate.p.phdr64[estate.segment].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
if ((estate.p.phdr64[estate.segment].p_paddr > ULONG_MAX) ||
|
|
||||||
((estate.p.phdr64[estate.segment].p_paddr + estate.p.phdr64[estate.segment].p_filesz) > ULONG_MAX) ||
|
|
||||||
((estate.p.phdr64[estate.segment].p_paddr + estate.p.phdr64[estate.segment].p_memsz) > ULONG_MAX)) {
|
|
||||||
printf("ELF segment exceeds address space\n");
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
start = estate.p.phdr64[estate.segment].p_paddr;
|
|
||||||
mid = start + estate.p.phdr64[estate.segment].p_filesz;
|
|
||||||
end = start + estate.p.phdr64[estate.segment].p_memsz;
|
|
||||||
istart = iend = ULONG_MAX;
|
|
||||||
if ((estate.p.phdr64[estate.segment].p_offset < ULONG_MAX) &&
|
|
||||||
((estate.p.phdr64[estate.segment].p_offset + estate.p.phdr64[estate.segment].p_filesz) < ULONG_MAX))
|
|
||||||
{
|
|
||||||
istart = estate.p.phdr64[estate.segment].p_offset;
|
|
||||||
iend = istart + estate.p.phdr64[estate.segment].p_filesz;
|
|
||||||
}
|
|
||||||
if (!prep_segment(start, mid, end, istart, iend)) {
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
if (!elf_prep_segment(start, mid, end, istart, iend)) {
|
|
||||||
return dead_download;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
estate.segment = -1;
|
|
||||||
estate.loc = 0;
|
|
||||||
estate.skip = 0;
|
|
||||||
estate.toread = 0;
|
|
||||||
return elf64_download;
|
|
||||||
}
|
|
||||||
|
|
||||||
static sector_t elf64_download(unsigned char *data, unsigned int len, int eof)
|
|
||||||
{
|
|
||||||
unsigned long skip_sectors = 0;
|
|
||||||
unsigned int offset; /* working offset in the current data block */
|
|
||||||
int i;
|
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
do {
|
|
||||||
if (estate.segment != -1) {
|
|
||||||
if (estate.skip) {
|
|
||||||
if (estate.skip >= len - offset) {
|
|
||||||
estate.skip -= len - offset;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
offset += estate.skip;
|
|
||||||
estate.skip = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (estate.toread) {
|
|
||||||
unsigned int cplen;
|
|
||||||
cplen = len - offset;
|
|
||||||
if (cplen >= estate.toread) {
|
|
||||||
cplen = estate.toread;
|
|
||||||
}
|
|
||||||
memcpy(phys_to_virt(estate.curaddr), data+offset, cplen);
|
|
||||||
estate.curaddr += cplen;
|
|
||||||
estate.toread -= cplen;
|
|
||||||
offset += cplen;
|
|
||||||
if (estate.toread)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Data left, but current segment finished - look for the next
|
|
||||||
* segment (in file offset order) that needs to be loaded.
|
|
||||||
* We can only seek forward, so select the program headers,
|
|
||||||
* in the correct order.
|
|
||||||
*/
|
|
||||||
estate.segment = -1;
|
|
||||||
for (i = 0; i < estate.e.elf64.e_phnum; i++) {
|
|
||||||
if (estate.p.phdr64[i].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
if (estate.p.phdr64[i].p_filesz == 0)
|
|
||||||
continue;
|
|
||||||
if (estate.p.phdr64[i].p_offset < estate.loc + offset)
|
|
||||||
continue; /* can't go backwards */
|
|
||||||
if ((estate.segment != -1) &&
|
|
||||||
(estate.p.phdr64[i].p_offset >= estate.p.phdr64[estate.segment].p_offset))
|
|
||||||
continue; /* search minimum file offset */
|
|
||||||
estate.segment = i;
|
|
||||||
}
|
|
||||||
if (estate.segment == -1) {
|
|
||||||
/* No more segments to be loaded, so just start the
|
|
||||||
* kernel. This saves a lot of network bandwidth if
|
|
||||||
* debug info is in the kernel but not loaded. */
|
|
||||||
goto elf_startkernel;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
estate.curaddr = estate.p.phdr64[estate.segment].p_paddr;
|
|
||||||
estate.skip = estate.p.phdr64[estate.segment].p_offset - (estate.loc + offset);
|
|
||||||
estate.toread = estate.p.phdr64[estate.segment].p_filesz;
|
|
||||||
#if ELF_DEBUG
|
|
||||||
printf("PHDR %d, size %#lX, curaddr %#lX\n",
|
|
||||||
estate.segment, estate.toread, estate.curaddr);
|
|
||||||
#endif
|
|
||||||
} while (offset < len);
|
|
||||||
|
|
||||||
estate.loc += len + (estate.skip & ~0x1ff);
|
|
||||||
skip_sectors = estate.skip >> 9;
|
|
||||||
estate.skip &= 0x1ff;
|
|
||||||
|
|
||||||
if (eof) {
|
|
||||||
unsigned long entry;
|
|
||||||
unsigned long machine;
|
|
||||||
elf_startkernel:
|
|
||||||
entry = estate.e.elf64.e_entry;
|
|
||||||
machine = estate.e.elf64.e_machine;
|
|
||||||
#if ELF_NOTES
|
|
||||||
if (estate.check_ip_checksum) {
|
|
||||||
unsigned long bytes = 0;
|
|
||||||
uint16_t sum, new_sum;
|
|
||||||
|
|
||||||
sum = ipchksum(&estate.e.elf64, sizeof(estate.e.elf64));
|
|
||||||
bytes = sizeof(estate.e.elf64);
|
|
||||||
#if ELF_DEBUG
|
|
||||||
printf("Ehdr: %hx %hx sz: %lx bytes: %lx\n",
|
|
||||||
sum, sum, bytes, bytes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
new_sum = ipchksum(estate.p.phdr64, sizeof(estate.p.phdr64[0]) * estate.e.elf64.e_phnum);
|
|
||||||
sum = add_ipchksums(bytes, sum, new_sum);
|
|
||||||
bytes += sizeof(estate.p.phdr64[0]) * estate.e.elf64.e_phnum;
|
|
||||||
#if ELF_DEBUG
|
|
||||||
printf("Phdr: %hx %hx sz: %lx bytes: %lx\n",
|
|
||||||
new_sum, sum,
|
|
||||||
sizeof(estate.p.phdr64[0]) * estate.e.elf64.e_phnum, bytes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for(i = 0; i < estate.e.elf64.e_phnum; i++) {
|
|
||||||
if (estate.p.phdr64[i].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
new_sum = ipchksum(phys_to_virt(estate.p.phdr64[i].p_paddr),
|
|
||||||
estate.p.phdr64[i].p_memsz);
|
|
||||||
sum = add_ipchksums(bytes, sum, new_sum);
|
|
||||||
bytes += estate.p.phdr64[i].p_memsz;
|
|
||||||
#if ELF_DEBUG
|
|
||||||
printf("seg%d: %hx %hx sz: %x bytes: %lx\n",
|
|
||||||
i, new_sum, sum,
|
|
||||||
estate.p.phdr64[i].p_memsz, bytes);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
if (estate.ip_checksum != sum) {
|
|
||||||
printf("\nImage checksum: %hx != computed checksum: %hx\n",
|
|
||||||
estate.ip_checksum, sum);
|
|
||||||
longjmp(restart_etherboot, -2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
done(1);
|
|
||||||
/* Fixup the offset to the program header so you can find the program headers from
|
|
||||||
* the ELF header mknbi needs this.
|
|
||||||
*/
|
|
||||||
estate.e.elf64.e_phoff = (char *)&estate.p - (char *)&estate.e;
|
|
||||||
elf_boot(machine,entry);
|
|
||||||
}
|
|
||||||
return skip_sectors;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ELF64_IMAGE */
|
|
|
@ -2,59 +2,10 @@
|
||||||
MISC Support Routines
|
MISC Support Routines
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <etherboot.h>
|
|
||||||
#include <console.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <byteswap.h>
|
||||||
|
#include <latch.h>
|
||||||
/**************************************************************************
|
#include <gpxe/in.h>
|
||||||
IPCHKSUM - Checksum IP Header
|
|
||||||
**************************************************************************/
|
|
||||||
uint16_t ipchksum(const void *data, unsigned long length)
|
|
||||||
{
|
|
||||||
unsigned long sum;
|
|
||||||
unsigned long i;
|
|
||||||
const uint8_t *ptr;
|
|
||||||
|
|
||||||
/* In the most straight forward way possible,
|
|
||||||
* compute an ip style checksum.
|
|
||||||
*/
|
|
||||||
sum = 0;
|
|
||||||
ptr = data;
|
|
||||||
for(i = 0; i < length; i++) {
|
|
||||||
unsigned long value;
|
|
||||||
value = ptr[i];
|
|
||||||
if (i & 1) {
|
|
||||||
value <<= 8;
|
|
||||||
}
|
|
||||||
/* Add the new value */
|
|
||||||
sum += value;
|
|
||||||
/* Wrap around the carry */
|
|
||||||
if (sum > 0xFFFF) {
|
|
||||||
sum = (sum + (sum >> 16)) & 0xFFFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (~cpu_to_le16(sum)) & 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t add_ipchksums(unsigned long offset, uint16_t sum, uint16_t new)
|
|
||||||
{
|
|
||||||
unsigned long checksum;
|
|
||||||
sum = ~sum & 0xFFFF;
|
|
||||||
new = ~new & 0xFFFF;
|
|
||||||
if (offset & 1) {
|
|
||||||
/* byte swap the sum if it came from an odd offset
|
|
||||||
* since the computation is endian independant this
|
|
||||||
* works.
|
|
||||||
*/
|
|
||||||
new = bswap_16(new);
|
|
||||||
}
|
|
||||||
checksum = sum + new;
|
|
||||||
if (checksum > 0xFFFF) {
|
|
||||||
checksum -= 0xFFFF;
|
|
||||||
}
|
|
||||||
return (~checksum) & 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
SLEEP
|
SLEEP
|
||||||
|
@ -68,24 +19,6 @@ unsigned int sleep(unsigned int secs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
INTERRUPTIBLE SLEEP
|
|
||||||
**************************************************************************/
|
|
||||||
void interruptible_sleep(int secs)
|
|
||||||
{
|
|
||||||
printf("<sleep>\n");
|
|
||||||
sleep(secs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
STRCASECMP (not entirely correct, but this will do for our purposes)
|
|
||||||
**************************************************************************/
|
|
||||||
int strcasecmp(const char *a, const char *b)
|
|
||||||
{
|
|
||||||
while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
|
|
||||||
return((*a & ~0x20) - (*b & ~0x20));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
INET_ATON - Convert an ascii x.x.x.x to binary form
|
INET_ATON - Convert an ascii x.x.x.x to binary form
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
#include "stddef.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include "proto.h"
|
|
||||||
|
|
||||||
static struct protocol protocols[0] __protocol_start;
|
|
||||||
static struct protocol default_protocols[0] __default_protocol_start;
|
|
||||||
static struct protocol protocols_end[0] __protocol_end;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Identify protocol given a name. name may be NULL, in which case
|
|
||||||
* the first default protocol (if any) will be used.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
struct protocol * identify_protocol ( const char *name ) {
|
|
||||||
struct protocol *proto = default_protocols;
|
|
||||||
|
|
||||||
if ( name ) {
|
|
||||||
for ( proto = protocols ; proto < protocols_end ; proto++ ) {
|
|
||||||
if ( strcmp ( name, proto->name ) == 0 )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return proto < protocols_end ? proto : NULL;
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* Copyright 2004 Linux Networx */
|
/* Copyright 2004 Linux Networx */
|
||||||
#ifdef PROTO_LACP
|
#ifdef PROTO_LACP
|
||||||
#if 0
|
#if 0
|
||||||
#include "etherboot.h"
|
|
||||||
#include "nic.h"
|
#include "nic.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <etherboot.h>
|
#include <latch.h>
|
||||||
|
|
||||||
static int32_t rnd_seed = 0;
|
static int32_t rnd_seed = 0;
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,14 @@ int strncmp(const char * cs,const char * ct,size_t count)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __HAVE_ARCH_STRCASECMP
|
||||||
|
int strcasecmp(const char *a, const char *b)
|
||||||
|
{
|
||||||
|
while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
|
||||||
|
return((*a & ~0x20) - (*b & ~0x20));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef __HAVE_ARCH_STRCHR
|
#ifndef __HAVE_ARCH_STRCHR
|
||||||
/**
|
/**
|
||||||
* strchr - Find the first occurrence of a character in a string
|
* strchr - Find the first occurrence of a character in a string
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
* your option) any later version.
|
* your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "etherboot.h"
|
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
/* Machine Independant timer helper functions */
|
/* Machine Independant timer helper functions */
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
/* Includes */
|
/* Includes */
|
||||||
|
|
||||||
#include "etherboot.h"
|
#include "etherboot.h"
|
||||||
#include "dev.h"
|
|
||||||
#include <gpxe/pci.h>
|
#include <gpxe/pci.h>
|
||||||
#include "nic.h"
|
#include "nic.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
@ -250,22 +249,19 @@ static int sis96x_get_mac_addr(struct pci_device * pci_dev __unused, struct nic
|
||||||
|
|
||||||
static int sis630e_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
|
static int sis630e_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
u8 reg;
|
u8 reg;
|
||||||
int i;
|
int i;
|
||||||
#if 0
|
|
||||||
struct bus_loc bus_loc;
|
struct bus_loc bus_loc;
|
||||||
#endif
|
|
||||||
union {
|
union {
|
||||||
struct bus_dev bus_dev;
|
struct bus_dev bus_dev;
|
||||||
struct pci_device isa_bridge;
|
struct pci_device isa_bridge;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* find PCI to ISA bridge */
|
/* find PCI to ISA bridge */
|
||||||
memset(&bus_loc, 0, sizeof(bus_loc));
|
memset(&bus_loc, 0, sizeof(bus_loc));
|
||||||
if ( ! find_by_driver ( &bus_loc, &u.bus_dev, &sis_bridge_driver, 0 ) )
|
if ( ! find_by_driver ( &bus_loc, &u.bus_dev, &sis_bridge_driver, 0 ) )
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
pci_read_config_byte(&u.isa_bridge, 0x48, ®);
|
pci_read_config_byte(&u.isa_bridge, 0x48, ®);
|
||||||
pci_write_config_byte(&u.isa_bridge, 0x48, reg | 0x40);
|
pci_write_config_byte(&u.isa_bridge, 0x48, reg | 0x40);
|
||||||
|
@ -278,6 +274,11 @@ static int sis630e_get_mac_addr(struct pci_device * pci_dev __unused, struct nic
|
||||||
pci_write_config_byte(&u.isa_bridge, 0x48, reg & ~0x40);
|
pci_write_config_byte(&u.isa_bridge, 0x48, reg & ~0x40);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Does not work with current bus/device model */
|
||||||
|
memset ( nic->node_addr, 0, sizeof ( nic->node_addr ) );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,280 +0,0 @@
|
||||||
#ifndef DEV_H
|
|
||||||
#define DEV_H
|
|
||||||
|
|
||||||
#include "stdint.h"
|
|
||||||
#include "string.h"
|
|
||||||
#include <gpxe/buffer.h>
|
|
||||||
#include "dhcp.h" /* for dhcp_dev_id */
|
|
||||||
#include <gpxe/tables.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Forward declarations
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
struct type_dev;
|
|
||||||
struct type_driver;
|
|
||||||
struct bus_driver;
|
|
||||||
struct bus_dev;
|
|
||||||
struct device_driver;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When looking at the following data structures, mentally substitute
|
|
||||||
* "<bus>_" in place of "bus_" and everything will become clear.
|
|
||||||
* "struct bus_location" becomes "struct <bus>_location", which means
|
|
||||||
* "the location of a device on a <bus> bus", where <bus> is a
|
|
||||||
* particular type of bus such as "pci" or "isapnp".
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A physical device location on a bus.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define BUS_LOC_SIZE 8
|
|
||||||
struct bus_loc {
|
|
||||||
char bytes[BUS_LOC_SIZE];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A structure fully describing a physical device on a bus.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define BUS_DEV_SIZE 32
|
|
||||||
struct bus_dev {
|
|
||||||
char bytes[BUS_DEV_SIZE];
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Individual buses will have different sizes for their <bus>_location
|
|
||||||
* and <bus>_device structures. We need to be able to allocate static
|
|
||||||
* storage that's large enough to contain these structures for any
|
|
||||||
* bus type that's being used in the current binary.
|
|
||||||
*
|
|
||||||
* We can't just create a union of all the various types, because some
|
|
||||||
* may be architecture-dependent (and some are even embedded in
|
|
||||||
* specific drivers, e.g. 3c509), so this would quickly get messy.
|
|
||||||
*
|
|
||||||
* We could use the magic of common symbols. Each bus could declare a
|
|
||||||
* common symbol with the name "_bus_dev" of the correct size; this
|
|
||||||
* is easily done using code like
|
|
||||||
* struct pci_device _bus_dev;
|
|
||||||
* The linker would then use the largest size of the "_bus_dev" symbol
|
|
||||||
* in any included object, thus giving us a single _bus_dev symbol of
|
|
||||||
* *exactly* the required size. However, there's no way to extract
|
|
||||||
* the size of this symbol, either directly as a linker symbol
|
|
||||||
* ("_bus_dev_size = SIZEOF(_bus_dev)"; the linker language just
|
|
||||||
* doesn't provide this construct) or via any linker trickery I can
|
|
||||||
* think of (such as creating a special common symbol section just for
|
|
||||||
* this symbol then using SIZE(section) to read the size of the
|
|
||||||
* section; ld recognises only a single common symbol section called
|
|
||||||
* "COMMON").
|
|
||||||
*
|
|
||||||
* Since there's no way to get the size of the symbol, this
|
|
||||||
* effectively limits us to just one instance of the symbol. This is
|
|
||||||
* all very well for the simple case of "just boot from any single
|
|
||||||
* device you can", but becomes limiting when you want to do things
|
|
||||||
* like introducing PCMCIA buses (which must instantiate other devices
|
|
||||||
* such as PCMCIA controllers).
|
|
||||||
*
|
|
||||||
* So, we declare the maximum sizes of these constructions to be
|
|
||||||
* compile-time constants. Each individual bus driver should define
|
|
||||||
* its own struct <bus>_location and struct <bus>_device however it
|
|
||||||
* likes, and can freely cast pointers from struct bus_loc to
|
|
||||||
* struct <bus>_location (and similarly for bus_dev). To guard
|
|
||||||
* against bounding errors, each bus driver *MUST* use the macros
|
|
||||||
* BUS_LOC_CHECK() and BUS_DEV_CHECK(), as in:
|
|
||||||
*
|
|
||||||
* BUS_LOC_CHECK ( struct pci_location );
|
|
||||||
* BUS_DEV_CHECK ( struct pci_device );
|
|
||||||
*
|
|
||||||
* These macros will generate a link-time error if the size of the
|
|
||||||
* <bus> structure exceeds the declared maximum size.
|
|
||||||
*
|
|
||||||
* The macros will generate no binary object code, but must be placed
|
|
||||||
* inside a function (in order to generate syntactically valid C).
|
|
||||||
* The easiest wy to do this is to place them in the
|
|
||||||
* <bus>_next_location() function.
|
|
||||||
*
|
|
||||||
* If anyone can think of a better way of doing this that avoids *ALL*
|
|
||||||
* of the problems described above, please implement it!
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define BUS_LOC_CHECK(datatype) \
|
|
||||||
linker_assert( ( sizeof (datatype) <= sizeof (struct bus_loc) ), \
|
|
||||||
__BUS_LOC_SIZE_is_too_small__see_dev_h )
|
|
||||||
#define BUS_DEV_CHECK(datatype) \
|
|
||||||
linker_assert( ( sizeof (datatype) <= sizeof (struct bus_dev) ), \
|
|
||||||
__BUS_DEV_SIZE_is_too_small__see_dev_h )
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Bus-level operations.
|
|
||||||
*
|
|
||||||
* int next_location ( struct bus_loc * bus_loc )
|
|
||||||
*
|
|
||||||
* Increment bus_loc to point to the next possible device on
|
|
||||||
* the bus (e.g. the next PCI busdevfn, or the next ISAPnP CSN).
|
|
||||||
* If there are no more valid locations, return 0 and leave
|
|
||||||
* struct bus_loc zeroed, otherwise return true.
|
|
||||||
*
|
|
||||||
* int fill_device ( struct bus_dev *bus_dev,
|
|
||||||
* struct bus_loc *bus_loc )
|
|
||||||
*
|
|
||||||
* Fill out a bus_dev structure with the parameters for the
|
|
||||||
* device at bus_loc. (For example, fill in the PCI vendor
|
|
||||||
* and device IDs). Return true if there is a device physically
|
|
||||||
* present at this location, otherwise 0.
|
|
||||||
*
|
|
||||||
* int check_driver ( struct bus_dev *bus_dev,
|
|
||||||
* struct device_driver *device_driver )
|
|
||||||
*
|
|
||||||
* Test whether or not the specified driver is capable of driving
|
|
||||||
* the specified device by, for example, comparing the device's
|
|
||||||
* PCI IDs against the list of PCI IDs claimed by the driver.
|
|
||||||
*
|
|
||||||
* char * describe ( struct bus_dev *bus_dev )
|
|
||||||
*
|
|
||||||
* Return a text string describing the bus device bus_dev
|
|
||||||
* (e.g. "PCI 00:01.2")
|
|
||||||
*
|
|
||||||
* char * name ( struct bus_dev *bus_dev )
|
|
||||||
*
|
|
||||||
* Return a text string describing the bus device bus_dev
|
|
||||||
* (e.g. "dfe538")
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
struct bus_driver {
|
|
||||||
const char *name;
|
|
||||||
int ( *next_location ) ( struct bus_loc *bus_loc );
|
|
||||||
int ( *fill_device ) ( struct bus_dev *bus_dev,
|
|
||||||
struct bus_loc *bus_loc );
|
|
||||||
int ( *check_driver ) ( struct bus_dev *bus_dev,
|
|
||||||
struct device_driver *device_driver );
|
|
||||||
char * ( *describe_device ) ( struct bus_dev *bus_dev );
|
|
||||||
const char * ( *name_device ) ( struct bus_dev *bus_dev );
|
|
||||||
};
|
|
||||||
|
|
||||||
#define __bus_driver __table ( struct bus_driver, bus_driver, 01 )
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A structure fully describing the bus-independent parts of a
|
|
||||||
* particular type (e.g. nic or disk) of device.
|
|
||||||
*
|
|
||||||
* Unlike struct bus_dev, e can limit ourselves to having no more than
|
|
||||||
* one instance of this data structure. We therefore place an
|
|
||||||
* instance in each type driver file (e.g. nic.c), and simply use a
|
|
||||||
* pointer to the struct type_dev in the struct dev.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
struct type_dev;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A type driver (e.g. nic, disk)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
struct type_driver {
|
|
||||||
char *name;
|
|
||||||
struct type_dev *type_dev; /* single instance */
|
|
||||||
char * ( * describe_device ) ( struct type_dev *type_dev );
|
|
||||||
int ( * configure ) ( struct type_dev *type_dev );
|
|
||||||
int ( * load ) ( struct type_dev *type_dev, struct buffer *buffer );
|
|
||||||
};
|
|
||||||
|
|
||||||
#define __type_driver __table ( struct type_driver, type_driver, 01 )
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A driver for a device.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
struct device_driver {
|
|
||||||
const char *name;
|
|
||||||
struct type_driver *type_driver;
|
|
||||||
struct bus_driver *bus_driver;
|
|
||||||
struct bus_driver_info *bus_driver_info;
|
|
||||||
int ( * probe ) ( struct type_dev *type_dev,
|
|
||||||
struct bus_dev *bus_dev );
|
|
||||||
void ( * disable ) ( struct type_dev *type_dev,
|
|
||||||
struct bus_dev *bus_dev );
|
|
||||||
};
|
|
||||||
|
|
||||||
#define __device_driver __table ( struct device_driver, device_driver, 01 )
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define DRIVER(_name,_type_driver,_bus_driver,_bus_info, \
|
|
||||||
_probe,_disable) \
|
|
||||||
struct device_driver device_ ## _bus_info __device_driver = { \
|
|
||||||
.name = _name, \
|
|
||||||
.type_driver = &_type_driver, \
|
|
||||||
.bus_driver = &_bus_driver, \
|
|
||||||
.bus_driver_info = ( struct bus_driver_info * ) &_bus_info, \
|
|
||||||
.probe = ( int (*) () ) _probe, \
|
|
||||||
.disable = ( void (*) () ) _disable, \
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DRIVER(a,b,c,d,e,f)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A bootable device, comprising a physical device on a bus, a driver
|
|
||||||
* for that device, and a type device
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
struct dev {
|
|
||||||
struct bus_driver *bus_driver;
|
|
||||||
struct bus_loc bus_loc;
|
|
||||||
struct bus_dev bus_dev;
|
|
||||||
struct device_driver *device_driver;
|
|
||||||
struct type_driver *type_driver;
|
|
||||||
struct type_dev *type_dev;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The current boot device */
|
|
||||||
extern struct dev dev;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions in dev.c
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
extern void print_drivers ( void );
|
|
||||||
extern int find_any ( struct bus_driver **bus_driver, struct bus_loc *bus_loc,
|
|
||||||
struct bus_dev *bus_dev, signed int skip );
|
|
||||||
extern int find_by_device ( struct device_driver **device_driver,
|
|
||||||
struct bus_driver *bus_driver,
|
|
||||||
struct bus_dev *bus_dev,
|
|
||||||
signed int skip );
|
|
||||||
extern int find_by_driver ( struct bus_loc *bus_loc, struct bus_dev *bus_dev,
|
|
||||||
struct device_driver *device_driver,
|
|
||||||
signed int skip );
|
|
||||||
extern int find_any_with_driver ( struct dev *dev, signed int skip );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions inlined to save space
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Probe a device */
|
|
||||||
static inline int probe ( struct dev *dev ) {
|
|
||||||
return dev->device_driver->probe ( dev->type_dev, &dev->bus_dev );
|
|
||||||
}
|
|
||||||
/* Disable a device */
|
|
||||||
static inline void disable ( struct dev *dev ) {
|
|
||||||
dev->device_driver->disable ( dev->type_dev, &dev->bus_dev );
|
|
||||||
}
|
|
||||||
/* Set the default boot device */
|
|
||||||
static inline void select_device ( struct dev *dev,
|
|
||||||
struct bus_driver *bus_driver,
|
|
||||||
struct bus_loc *bus_loc ) {
|
|
||||||
dev->bus_driver = bus_driver;
|
|
||||||
memcpy ( &dev->bus_loc, bus_loc, sizeof ( dev->bus_loc ) );
|
|
||||||
}
|
|
||||||
/* Configure a device */
|
|
||||||
static inline int configure ( struct dev *dev ) {
|
|
||||||
return dev->type_driver->configure ( dev->type_dev );
|
|
||||||
}
|
|
||||||
/* Boot from a device */
|
|
||||||
static inline int load ( struct dev *dev, struct buffer *buffer ) {
|
|
||||||
return dev->type_driver->load ( dev->type_dev, buffer );
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* DEV_H */
|
|
|
@ -1,11 +0,0 @@
|
||||||
#ifndef MAIN_H
|
|
||||||
#define MAIN_H
|
|
||||||
|
|
||||||
#include "dev.h"
|
|
||||||
|
|
||||||
extern struct dev dev;
|
|
||||||
|
|
||||||
extern int main ( void );
|
|
||||||
extern void set_pci_device ( uint16_t busdevfn );
|
|
||||||
|
|
||||||
#endif /* MAIN_H */
|
|
|
@ -3,8 +3,6 @@
|
||||||
#ifndef PCMCIA_H
|
#ifndef PCMCIA_H
|
||||||
#define PCMCIA_H
|
#define PCMCIA_H
|
||||||
|
|
||||||
#include "etherboot.h"
|
|
||||||
|
|
||||||
typedef unsigned char u_char;
|
typedef unsigned char u_char;
|
||||||
typedef unsigned short u_short;
|
typedef unsigned short u_short;
|
||||||
typedef unsigned int u_int;
|
typedef unsigned int u_int;
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
#ifndef PROTO_H
|
|
||||||
#define PROTO_H
|
|
||||||
|
|
||||||
#include <gpxe/tables.h>
|
|
||||||
#include <gpxe/buffer.h>
|
|
||||||
#include <gpxe/in.h>
|
|
||||||
|
|
||||||
struct protocol {
|
|
||||||
char *name;
|
|
||||||
uint16_t default_port;
|
|
||||||
int ( * load ) ( char *url, struct sockaddr_in *server, char *file,
|
|
||||||
struct buffer *buffer );
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Protocols that should be used if no explicit protocol is specified
|
|
||||||
* (i.e. tftp) should use __default_protocol; all other protocols
|
|
||||||
* should use __protocol.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define __protocol_start __table_start ( struct protocol, protocol )
|
|
||||||
#define __protocol __table ( struct protocol, protocol, 01 )
|
|
||||||
#define __default_protocol_start __table ( struct protocol, protocol, 02 )
|
|
||||||
#define __default_protocol __table ( struct protocol, protocol, 03 )
|
|
||||||
#define __protocol_end __table_end ( struct protocol, protocol )
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions in proto.c
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
extern struct protocol * identify_protocol ( const char *name );
|
|
||||||
|
|
||||||
#endif /* PROTO_H */
|
|
|
@ -33,8 +33,6 @@
|
||||||
\*********************************************************************/
|
\*********************************************************************/
|
||||||
|
|
||||||
#ifdef DOWNLOAD_PROTO_FSP
|
#ifdef DOWNLOAD_PROTO_FSP
|
||||||
#include "etherboot.h"
|
|
||||||
#include "nic.h"
|
|
||||||
|
|
||||||
#define FSP_PORT 21
|
#define FSP_PORT 21
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
|
|
||||||
#include <ip.h>
|
#include <ip.h>
|
||||||
#include <igmp.h>
|
#include <igmp.h>
|
||||||
#include <background.h>
|
|
||||||
#include <nic.h>
|
#if 0
|
||||||
#include <etherboot.h>
|
|
||||||
|
|
||||||
static unsigned long last_igmpv1 = 0;
|
static unsigned long last_igmpv1 = 0;
|
||||||
static struct igmptable_t igmptable[MAX_IGMP];
|
static struct igmptable_t igmptable[MAX_IGMP];
|
||||||
|
@ -164,3 +163,5 @@ void join_group ( int slot, unsigned long group ) {
|
||||||
igmptable[slot].time = currticks();
|
igmptable[slot].time = currticks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#include "etherboot.h"
|
#if 0
|
||||||
|
|
||||||
#include <gpxe/init.h>
|
#include <gpxe/init.h>
|
||||||
#include "proto.h"
|
|
||||||
#include <gpxe/in.h>
|
#include <gpxe/in.h>
|
||||||
#include "nic.h"
|
|
||||||
|
|
||||||
/* NOTE: the NFS code is heavily inspired by the NetBSD netboot code (read:
|
/* NOTE: the NFS code is heavily inspired by the NetBSD netboot code (read:
|
||||||
* large portions are copied verbatim) as distributed in OSKit 0.97. A few
|
* large portions are copied verbatim) as distributed in OSKit 0.97. A few
|
||||||
|
@ -613,3 +612,5 @@ struct protocol nfs_protocol __protocol = {
|
||||||
.default_port = SUNRPC_PORT,
|
.default_port = SUNRPC_PORT,
|
||||||
.load = nfs,
|
.load = nfs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
#include "etherboot.h"
|
#if 0
|
||||||
#include "proto.h"
|
|
||||||
#include "nic.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IMPORTANT
|
* IMPORTANT
|
||||||
|
@ -539,3 +537,5 @@ struct protocol slam_protocol __protocol = {
|
||||||
.default_port = SLAM_PORT,
|
.default_port = SLAM_PORT,
|
||||||
.load = url_slam,
|
.load = url_slam,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Reference in New Issue