mirror of
https://github.com/xcat2/xNBA.git
synced 2024-12-14 07:11:32 +00:00
Removed the Etherboot-specific ELF-image code and replaced it with a
generic ELF loader, to be used by the multiboot code.
This commit is contained in:
parent
10980c12ee
commit
7ad1c2eaa8
@ -1,136 +0,0 @@
|
||||
#include "etherboot.h"
|
||||
#include "elf.h"
|
||||
#include "memsizes.h"
|
||||
|
||||
|
||||
#define NAME "Etherboot"
|
||||
|
||||
#if defined(PCBIOS)
|
||||
#define FIRMWARE "PCBIOS"
|
||||
#endif
|
||||
#if defined(LINUXBIOS)
|
||||
#define FIRMWARE "LinuxBIOS"
|
||||
#endif
|
||||
#if !defined(FIRMWARE)
|
||||
#error "No BIOS selected"
|
||||
#endif
|
||||
|
||||
#define SZ(X) ((sizeof(X)+3) & ~3)
|
||||
#define CP(D,S) (memcpy(&(D), &(S), sizeof(S)))
|
||||
|
||||
struct elf_notes {
|
||||
/* The note header */
|
||||
struct Elf_Bhdr hdr;
|
||||
|
||||
/* First the Fixed sized entries that must be well aligned */
|
||||
|
||||
/* Pointer to bootp data */
|
||||
Elf_Nhdr nf1;
|
||||
char nf1_name[SZ(EB_PARAM_NOTE)];
|
||||
uint32_t nf1_bootp_data;
|
||||
|
||||
/* Pointer to ELF header */
|
||||
Elf_Nhdr nf2;
|
||||
char nf2_name[SZ(EB_PARAM_NOTE)];
|
||||
uint32_t nf2_header;
|
||||
|
||||
/* A copy of the i386 memory map */
|
||||
Elf_Nhdr nf3;
|
||||
char nf3_name[SZ(EB_PARAM_NOTE)];
|
||||
struct meminfo nf3_meminfo;
|
||||
|
||||
/* Then the variable sized data string data where alignment does not matter */
|
||||
|
||||
/* The bootloader name */
|
||||
Elf_Nhdr nv1;
|
||||
char nv1_desc[SZ(NAME)];
|
||||
/* The bootloader version */
|
||||
Elf_Nhdr nv2;
|
||||
char nv2_desc[SZ(VERSION)];
|
||||
/* The firmware type */
|
||||
Elf_Nhdr nv3;
|
||||
char nv3_desc[SZ(FIRMWARE)];
|
||||
/* Name of the loaded image */
|
||||
Elf_Nhdr nv4;
|
||||
char nv4_loaded_image[128];
|
||||
/* An empty command line */
|
||||
Elf_Nhdr nv5;
|
||||
char nv5_cmdline[SZ("")];
|
||||
};
|
||||
|
||||
#define ELF_NOTE_COUNT (3 + 5)
|
||||
|
||||
static struct elf_notes notes;
|
||||
struct Elf_Bhdr *prepare_boot_params(void *header)
|
||||
{
|
||||
memset(¬es, 0, sizeof(notes));
|
||||
notes.hdr.b_signature = ELF_BHDR_MAGIC;
|
||||
notes.hdr.b_size = sizeof(notes);
|
||||
notes.hdr.b_checksum = 0;
|
||||
notes.hdr.b_records = ELF_NOTE_COUNT;
|
||||
|
||||
/* Initialize the fixed length entries. */
|
||||
notes.nf1.n_namesz = sizeof(EB_PARAM_NOTE);
|
||||
notes.nf1.n_descsz = sizeof(notes.nf1_bootp_data);
|
||||
notes.nf1.n_type = EB_BOOTP_DATA;
|
||||
CP(notes.nf1_name, EB_PARAM_NOTE);
|
||||
notes.nf1_bootp_data = virt_to_phys(&bootp_data);
|
||||
|
||||
notes.nf2.n_namesz = sizeof(EB_PARAM_NOTE);
|
||||
notes.nf2.n_descsz = sizeof(notes.nf2_header);
|
||||
notes.nf2.n_type = EB_HEADER;
|
||||
CP(notes.nf2_name, EB_PARAM_NOTE);
|
||||
notes.nf2_header = virt_to_phys(header);
|
||||
|
||||
notes.nf3.n_namesz = sizeof(EB_PARAM_NOTE);
|
||||
notes.nf3.n_descsz = sizeof(notes.nf3_meminfo);
|
||||
notes.nf3.n_type = EB_I386_MEMMAP;
|
||||
CP(notes.nf3_name, EB_PARAM_NOTE);
|
||||
memcpy(¬es.nf3_meminfo, &meminfo, sizeof(meminfo));
|
||||
|
||||
/* Initialize the variable length entries */
|
||||
notes.nv1.n_namesz = 0;
|
||||
notes.nv1.n_descsz = sizeof(NAME);
|
||||
notes.nv1.n_type = EBN_BOOTLOADER_NAME;
|
||||
CP(notes.nv1_desc, NAME);
|
||||
|
||||
notes.nv2.n_namesz = 0;
|
||||
notes.nv2.n_descsz = sizeof(VERSION);
|
||||
notes.nv2.n_type = EBN_BOOTLOADER_VERSION;
|
||||
CP(notes.nv2_desc, VERSION);
|
||||
|
||||
notes.nv3.n_namesz = 0;
|
||||
notes.nv3.n_descsz = sizeof(FIRMWARE);
|
||||
notes.nv3.n_type = EBN_FIRMWARE_TYPE;
|
||||
CP(notes.nv3_desc, FIRMWARE);
|
||||
|
||||
/* Attempt to pass the name of the loaded image */
|
||||
notes.nv4.n_namesz = 0;
|
||||
notes.nv4.n_descsz = sizeof(notes.nv4_loaded_image);
|
||||
notes.nv4.n_type = EBN_LOADED_IMAGE;
|
||||
memcpy(¬es.nv4_loaded_image, KERNEL_BUF, sizeof(notes.nv4_loaded_image));
|
||||
|
||||
/* Pass an empty command line for now */
|
||||
notes.nv5.n_namesz = 0;
|
||||
notes.nv5.n_descsz = sizeof("");
|
||||
notes.nv5.n_type = EBN_COMMAND_LINE;
|
||||
CP(notes.nv5_cmdline, "");
|
||||
|
||||
|
||||
notes.hdr.b_checksum = ipchksum(¬es, sizeof(notes));
|
||||
/* Like UDP invert a 0 checksum to show that a checksum is present */
|
||||
if (notes.hdr.b_checksum == 0) {
|
||||
notes.hdr.b_checksum = 0xffff;
|
||||
}
|
||||
return ¬es.hdr;
|
||||
}
|
||||
|
||||
int elf_start(unsigned long machine __unused_i386, unsigned long entry, unsigned long params)
|
||||
{
|
||||
#if defined(CONFIG_X86_64)
|
||||
if (machine == EM_X86_64) {
|
||||
return xstart_lm(entry, params);
|
||||
}
|
||||
#endif
|
||||
return xstart32(entry, params);
|
||||
}
|
130
src/image/elf.c
Normal file
130
src/image/elf.c
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* ELF image format
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <elf.h>
|
||||
#include <gpxe/uaccess.h>
|
||||
#include <gpxe/segment.h>
|
||||
|
||||
typedef Elf32_Ehdr Elf_Ehdr;
|
||||
typedef Elf32_Phdr Elf_Phdr;
|
||||
typedef Elf32_Off Elf_Off;
|
||||
|
||||
/** An ELF file */
|
||||
struct elf {
|
||||
/** ELF file image */
|
||||
userptr_t image;
|
||||
/** Length of ELF file image */
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load ELF segment into memory
|
||||
*
|
||||
* @v elf ELF file
|
||||
* @v phdr ELF program header
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int elf_load_segment ( struct elf *elf, Elf_Phdr *phdr ) {
|
||||
physaddr_t dest;
|
||||
userptr_t buffer;
|
||||
int rc;
|
||||
|
||||
/* Do nothing for non-PT_LOAD segments */
|
||||
if ( phdr->p_type != PT_LOAD )
|
||||
return 0;
|
||||
|
||||
/* Check segment lies within image */
|
||||
if ( ( phdr->p_offset + phdr->p_filesz ) > elf->len ) {
|
||||
DBG ( "ELF segment outside ELF file\n" );
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
/* Find start address: use physical address for preference,
|
||||
* fall back to virtual address if no physical address
|
||||
* supplied.
|
||||
*/
|
||||
dest = phdr->p_paddr;
|
||||
if ( ! dest )
|
||||
dest = phdr->p_vaddr;
|
||||
if ( ! dest ) {
|
||||
DBG ( "ELF segment loads to physical address 0\n" );
|
||||
return -ENOEXEC;
|
||||
}
|
||||
buffer = phys_to_user ( dest );
|
||||
|
||||
DBG ( "ELF loading segment [%lx,%lx) to [%lx,%lx,%lx)\n",
|
||||
phdr->p_offset, ( phdr->p_offset + phdr->p_filesz ),
|
||||
phdr->p_paddr, ( phdr->p_paddr + phdr->p_filesz ),
|
||||
( phdr->p_paddr + phdr->p_memsz ) );
|
||||
|
||||
/* Verify and prepare segment */
|
||||
if ( ( rc = prep_segment ( buffer, phdr->p_filesz,
|
||||
phdr->p_memsz ) ) != 0 ) {
|
||||
DBG ( "ELF could not prepare segment: %s\n", strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Copy image to segment */
|
||||
copy_user ( buffer, 0, elf->image, phdr->p_offset, phdr->p_filesz );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load ELF image into memory
|
||||
*
|
||||
* @v elf ELF file
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int elf_load ( struct elf *elf ) {
|
||||
Elf_Ehdr ehdr;
|
||||
Elf_Phdr phdr;
|
||||
Elf_Off phoff;
|
||||
unsigned int phnum;
|
||||
int rc;
|
||||
|
||||
/* Read ELF header */
|
||||
copy_from_user ( &ehdr, elf->image, 0, sizeof ( ehdr ) );
|
||||
if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) {
|
||||
DBG ( "Invalid ELF signature\n" );
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
/* Read ELF program headers */
|
||||
for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
|
||||
phoff += ehdr.e_phentsize, phnum-- ) {
|
||||
if ( phoff > elf->len ) {
|
||||
DBG ( "ELF program header %d outside ELF image\n",
|
||||
phnum );
|
||||
return -ENOEXEC;
|
||||
}
|
||||
copy_from_user ( &phdr, elf->image, phoff, sizeof ( phdr ) );
|
||||
if ( ( rc = elf_load_segment ( elf, &phdr ) ) != 0 )
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -121,6 +121,7 @@
|
||||
#define ELFMAG3 'F'
|
||||
|
||||
#define ELFMAG "\177ELF"
|
||||
#define SELFMAG 4
|
||||
|
||||
#define EI_CLASS 4 /* File class byte index */
|
||||
#define ELFCLASSNONE 0 /* Invalid class */
|
||||
@ -141,6 +142,9 @@
|
||||
#define ELF32_PHDR_SIZE (8*4) /* Size of an elf program header */
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* ELF definitions common to all 32-bit architectures.
|
||||
*/
|
||||
@ -229,6 +233,4 @@ typedef struct {
|
||||
|
||||
#endif /* ASSEMBLY */
|
||||
|
||||
#include "elf_boot.h"
|
||||
|
||||
#endif /* ELF_H */
|
||||
|
@ -1,84 +0,0 @@
|
||||
#ifndef ELF_BOOT_H
|
||||
#define ELF_BOOT_H
|
||||
|
||||
|
||||
/* This defines the structure of a table of parameters useful for ELF
|
||||
* bootable images. These parameters are all passed and generated
|
||||
* by the bootloader to the booted image. For simplicity and
|
||||
* consistency the Elf Note format is reused.
|
||||
*
|
||||
* All of the information must be Position Independent Data.
|
||||
* That is it must be safe to relocate the whole ELF boot parameter
|
||||
* block without changing the meaning or correctnes of the data.
|
||||
* Additionally it must be safe to permute the order of the ELF notes
|
||||
* to any possible permutation without changing the meaning or correctness
|
||||
* of the data.
|
||||
*
|
||||
*/
|
||||
|
||||
#define ELF_BHDR_MAGIC 0x0E1FB007
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
#include <stdint.h>
|
||||
typedef uint16_t Elf_Half;
|
||||
typedef uint32_t Elf_Word;
|
||||
|
||||
typedef struct Elf_Bhdr
|
||||
{
|
||||
Elf_Word b_signature; /* "0x0E1FB007" */
|
||||
Elf_Word b_size;
|
||||
Elf_Half b_checksum;
|
||||
Elf_Half b_records;
|
||||
} Elf_Bhdr;
|
||||
|
||||
typedef struct Elf_Nhdr
|
||||
{
|
||||
Elf_Word n_namesz; /* Length of the note's name. */
|
||||
Elf_Word n_descsz; /* Length of the note's descriptor. */
|
||||
Elf_Word n_type; /* Type of the note. */
|
||||
} Elf_Nhdr;
|
||||
|
||||
#endif /* ASSEMBLY */
|
||||
|
||||
/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */
|
||||
#define ELF_NOTE_BOOT "ELFBoot"
|
||||
|
||||
#define EIN_PROGRAM_NAME 0x00000001
|
||||
/* The program in this ELF file */
|
||||
#define EIN_PROGRAM_VERSION 0x00000002
|
||||
/* The version of the program in this ELF file */
|
||||
#define EIN_PROGRAM_CHECKSUM 0x00000003
|
||||
/* ip style checksum of the memory image. */
|
||||
|
||||
|
||||
/* Notes that are passed to a loaded image */
|
||||
/* For standard notes n_namesz must be zero */
|
||||
#define EBN_FIRMWARE_TYPE 0x00000001
|
||||
/* ASCIZ name of the platform firmware. */
|
||||
#define EBN_BOOTLOADER_NAME 0x00000002
|
||||
/* This specifies just the ASCIZ name of the bootloader */
|
||||
#define EBN_BOOTLOADER_VERSION 0x00000003
|
||||
/* This specifies the version of the bootloader as an ASCIZ string */
|
||||
#define EBN_COMMAND_LINE 0x00000004
|
||||
/* This specifies a command line that can be set by user interaction,
|
||||
* and is provided as a free form ASCIZ string to the loaded image.
|
||||
*/
|
||||
#define EBN_NOP 0x00000005
|
||||
/* A note nop note has no meaning, useful for inserting explicit padding */
|
||||
#define EBN_LOADED_IMAGE 0x00000006
|
||||
/* An ASCIZ string naming the loaded image */
|
||||
|
||||
|
||||
/* Etherboot specific notes */
|
||||
#define EB_PARAM_NOTE "Etherboot"
|
||||
#define EB_IA64_SYSTAB 0x00000001
|
||||
#define EB_IA64_MEMMAP 0x00000002
|
||||
#define EB_IA64_FPSWA 0x00000003
|
||||
#define EB_IA64_CONINFO 0x00000004
|
||||
#define EB_BOOTP_DATA 0x00000005
|
||||
#define EB_HEADER 0x00000006
|
||||
#define EB_IA64_IMAGE_HANDLE 0x00000007
|
||||
#define EB_I386_MEMMAP 0x00000008
|
||||
|
||||
|
||||
#endif /* ELF_BOOT_H */
|
Loading…
Reference in New Issue
Block a user