Dead code removal.

Kill off use of etherboot.h outside drivers/net.
This commit is contained in:
Michael Brown
2007-07-14 15:42:26 +01:00
parent 95c07736cb
commit e330db3c74
20 changed files with 30 additions and 1321 deletions

View File

@@ -9,7 +9,6 @@
* move to Etherboot by LYH
*/
#include "etherboot.h"
#include "console.h"
#include <gpxe/init.h>
#include <gpxe/pci.h>

View File

@@ -5,10 +5,6 @@
* your option) any later version.
*/
#include "etherboot.h"
#include "dev.h"
#include "console.h"
#include "config/general.h"
/*

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -2,59 +2,10 @@
MISC Support Routines
**************************************************************************/
#include <etherboot.h>
#include <console.h>
#include <stdlib.h>
#include <stdio.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;
}
#include <byteswap.h>
#include <latch.h>
#include <gpxe/in.h>
/**************************************************************************
SLEEP
@@ -68,24 +19,6 @@ unsigned int sleep(unsigned int secs)
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
**************************************************************************/

View File

@@ -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;
}

View File

@@ -1,7 +1,6 @@
/* Copyright 2004 Linux Networx */
#ifdef PROTO_LACP
#if 0
#include "etherboot.h"
#include "nic.h"
#include "timer.h"
#endif

View File

@@ -5,7 +5,7 @@
*/
#include <stdlib.h>
#include <etherboot.h>
#include <latch.h>
static int32_t rnd_seed = 0;

View File

@@ -189,6 +189,14 @@ int strncmp(const char * cs,const char * ct,size_t count)
}
#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
/**
* strchr - Find the first occurrence of a character in a string

View File

@@ -7,7 +7,6 @@
* your option) any later version.
*/
#include "etherboot.h"
#include "timer.h"
/* Machine Independant timer helper functions */