Updates to produce a linuxBIOS table. Modeled on the earlier
uniform_boot work, but relocated. You need the new mkelfImage to use the elf boot format. Previous tables were updated so I could find both the start and the end of where they were written in memory. Minor p4dc6 updates, to disable some debugging code. The mkelfImage-1.9 is checked in as util/mkelfImage
This commit is contained in:
parent
d9db3cd6c4
commit
9cda94e6d2
32 changed files with 3383 additions and 117 deletions
|
|
@ -1 +1,2 @@
|
|||
object boot.o
|
||||
object linuxbios_table.o
|
||||
|
|
|
|||
|
|
@ -1,86 +1,59 @@
|
|||
#include <boot/uniform_boot.h>
|
||||
#include <ip_checksum.h>
|
||||
#include <boot/elf.h>
|
||||
#include <boot/elf_boot.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef CMD_LINE
|
||||
#define CMD_LINE ""
|
||||
#endif
|
||||
|
||||
/* FIXME: the current placement of ube_all could lead to problems...
|
||||
* It should be in a location normally reserved for the bios.
|
||||
*/
|
||||
|
||||
|
||||
#define UPSZ(X) ((sizeof(X) + 3) &~3)
|
||||
|
||||
static struct {
|
||||
struct uniform_boot_header header;
|
||||
struct linuxbios_header lb_header;
|
||||
struct {
|
||||
struct {
|
||||
struct ube_memory memory;
|
||||
struct ube_memory_range range[2];
|
||||
} mem;
|
||||
}env;
|
||||
unsigned char command_line[1024];
|
||||
} ube_all = {
|
||||
.header = {
|
||||
.header_bytes = sizeof(ube_all.header),
|
||||
.header_checksum = 0,
|
||||
.arg = (unsigned long)&ube_all.command_line,
|
||||
.arg_bytes = sizeof(ube_all.command_line),
|
||||
.env = (unsigned long)&ube_all.env,
|
||||
.env_bytes = sizeof(ube_all.env),
|
||||
Elf_Bhdr hdr;
|
||||
Elf_Nhdr ft_hdr;
|
||||
unsigned char ft_desc[UPSZ(FIRMWARE_TYPE)];
|
||||
Elf_Nhdr bl_hdr;
|
||||
unsigned char bl_desc[UPSZ(BOOTLOADER)];
|
||||
Elf_Nhdr blv_hdr;
|
||||
unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
|
||||
Elf_Nhdr cmd_hdr;
|
||||
unsigned char cmd_desc[UPSZ(CMD_LINE)];
|
||||
} elf_boot_notes = {
|
||||
.hdr = {
|
||||
.b_signature = 0x0E1FB007,
|
||||
.b_size = sizeof(elf_boot_notes),
|
||||
.b_checksum = 0,
|
||||
.b_records = 4,
|
||||
},
|
||||
.lb_header = {
|
||||
.signature = { 'L', 'B', 'I', 'O' },
|
||||
.header_bytes = sizeof(ube_all.lb_header),
|
||||
.header_checksum = 0,
|
||||
.env_bytes = sizeof(ube_all.env),
|
||||
.env_checksum = 0,
|
||||
.env_entries = 0,
|
||||
.ft_hdr = {
|
||||
.n_namesz = 0,
|
||||
.n_descsz = sizeof(FIRMWARE_TYPE),
|
||||
.n_type = EBN_FIRMWARE_TYPE,
|
||||
},
|
||||
.env = {
|
||||
.mem = {
|
||||
.memory = {
|
||||
.tag = UBE_TAG_MEMORY,
|
||||
.size = sizeof(ube_all.env.mem),
|
||||
},
|
||||
.range = {
|
||||
#if 0
|
||||
{
|
||||
.start = 0,
|
||||
.size = 0xa0000, /* 640k */
|
||||
.type = UBE_MEM_RAM,
|
||||
},
|
||||
#else
|
||||
{
|
||||
.start = 4096, /* skip the first page */
|
||||
.size = 0x9f000, /* 640k */
|
||||
.type = UBE_MEM_RAM,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.start = 0x00100000, /* 1M */
|
||||
.size = 0, /* Fill in the size */
|
||||
.type = UBE_MEM_RAM,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
.ft_desc = FIRMWARE_TYPE,
|
||||
.bl_hdr = {
|
||||
.n_namesz = 0,
|
||||
.n_descsz = sizeof(BOOTLOADER),
|
||||
.n_type = EBN_BOOTLOADER_NAME,
|
||||
},
|
||||
.command_line = CMD_LINE,
|
||||
.bl_desc = BOOTLOADER,
|
||||
.blv_hdr = {
|
||||
.n_namesz = 0,
|
||||
.n_descsz = sizeof(BOOTLOADER_VERSION),
|
||||
.n_type = EBN_BOOTLOADER_VERSION,
|
||||
},
|
||||
.blv_desc = BOOTLOADER_VERSION,
|
||||
.cmd_hdr = {
|
||||
.n_namesz = 0,
|
||||
.n_descsz = sizeof(CMD_LINE),
|
||||
.n_type = EBN_COMMAND_LINE,
|
||||
},
|
||||
.cmd_desc = CMD_LINE,
|
||||
};
|
||||
|
||||
void *get_ube_pointer(unsigned long totalram)
|
||||
{
|
||||
ube_all.env.mem.range[1].size = ((totalram - 1024) << 10);
|
||||
ube_all.header.header_checksum = 0;
|
||||
ube_all.header.header_checksum =
|
||||
uniform_boot_compute_header_checksum(&ube_all.header);
|
||||
ube_all.lb_header.env_entries = 1; /* FIXME remove this hardcode.. */
|
||||
ube_all.lb_header.env_checksum =
|
||||
compute_checksum(&ube_all.env, sizeof(ube_all.env));
|
||||
ube_all.lb_header.header_checksum =
|
||||
compute_checksum(&ube_all.lb_header, sizeof(ube_all.lb_header));
|
||||
return &ube_all.header;
|
||||
}
|
||||
|
||||
int elf_check_arch(Elf_ehdr *ehdr)
|
||||
{
|
||||
|
|
@ -92,9 +65,11 @@ int elf_check_arch(Elf_ehdr *ehdr)
|
|||
|
||||
}
|
||||
|
||||
void jmp_to_elf_entry(void *entry, void *ube)
|
||||
void jmp_to_elf_entry(void *entry)
|
||||
{
|
||||
unsigned long type = 0x0A11B007;
|
||||
unsigned long type = 0x0E1FB007;
|
||||
elf_boot_notes.hdr.b_checksum =
|
||||
compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes));
|
||||
|
||||
/* Jump to kernel */
|
||||
__asm__ __volatile__(
|
||||
|
|
@ -104,7 +79,7 @@ void jmp_to_elf_entry(void *entry, void *ube)
|
|||
"popl %%ebx\n\t"
|
||||
"popl %%eax\n\t"
|
||||
"ret\n\t"
|
||||
:: "g" (entry), "g"(type), "g"(ube));
|
||||
:: "g" (entry), "g"(type), "g"(&elf_boot_notes));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
177
src/arch/i386/boot/linuxbios_table.c
Normal file
177
src/arch/i386/boot/linuxbios_table.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
#include <ip_checksum.h>
|
||||
#include <boot/linuxbios_tables.h>
|
||||
#include <boot/linuxbios_table.h>
|
||||
#include <printk.h>
|
||||
|
||||
struct lb_header *lb_table_init(unsigned long addr)
|
||||
{
|
||||
struct lb_header *header;
|
||||
|
||||
/* 16 byte align the address */
|
||||
addr += 15;
|
||||
addr &= ~15;
|
||||
|
||||
header = (void *)addr;
|
||||
header->signature[0] = 'L';
|
||||
header->signature[1] = 'B';
|
||||
header->signature[2] = 'I';
|
||||
header->signature[3] = 'O';
|
||||
header->header_bytes = sizeof(*header);
|
||||
header->header_checksum = 0;
|
||||
header->table_bytes = 0;
|
||||
header->table_checksum = 0;
|
||||
header->table_entries = 0;
|
||||
return header;
|
||||
}
|
||||
|
||||
struct lb_record *lb_first_record(struct lb_header *header)
|
||||
{
|
||||
struct lb_record *rec;
|
||||
rec = (void *)(((char *)header) + sizeof(*header));
|
||||
return rec;
|
||||
}
|
||||
|
||||
struct lb_record *lb_last_record(struct lb_header *header)
|
||||
{
|
||||
struct lb_record *rec;
|
||||
rec = (void *)(((char *)header) + sizeof(*header) + header->table_bytes);
|
||||
return rec;
|
||||
}
|
||||
|
||||
struct lb_record *lb_next_record(struct lb_record *rec)
|
||||
{
|
||||
rec = (void *)(((char *)rec) + rec->size);
|
||||
return rec;
|
||||
}
|
||||
|
||||
struct lb_record *lb_new_record(struct lb_header *header)
|
||||
{
|
||||
struct lb_record *rec;
|
||||
rec = lb_last_record(header);
|
||||
if (header->table_entries) {
|
||||
header->table_bytes += rec->size;
|
||||
}
|
||||
rec = lb_last_record(header);
|
||||
header->table_entries++;
|
||||
rec->tag = LB_TAG_UNUSED;
|
||||
rec->size = sizeof(*rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
|
||||
struct lb_memory *lb_memory(struct lb_header *header)
|
||||
{
|
||||
struct lb_record *rec;
|
||||
struct lb_memory *mem;
|
||||
rec = lb_new_record(header);
|
||||
mem = (struct lb_memory *)rec;
|
||||
mem->tag = LB_TAG_MEMORY;
|
||||
mem->size = sizeof(*mem);
|
||||
return mem;
|
||||
}
|
||||
|
||||
/* Some version of gcc have problems with 64 bit types so
|
||||
* take an unsigned long instead of a uint64_t for now.
|
||||
*/
|
||||
void lb_memory_range(struct lb_memory *mem,
|
||||
uint32_t type, unsigned long start, unsigned long size)
|
||||
{
|
||||
int entries;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
mem->map[entries].start = start;
|
||||
mem->map[entries].size = size;
|
||||
mem->map[entries].type = type;
|
||||
mem->size += sizeof(mem->map[0]);
|
||||
}
|
||||
|
||||
static void lb_reserve_table_memory(struct lb_header *head)
|
||||
{
|
||||
struct lb_record *rec, *last_rec;
|
||||
struct lb_memory *mem;
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
int i, entries;
|
||||
last_rec = lb_last_record(head);
|
||||
mem = 0;
|
||||
for(rec = lb_first_record(head); rec < last_rec; lb_next_record(rec)) {
|
||||
if (rec->tag == LB_TAG_MEMORY) {
|
||||
mem = (struct lb_memory *)rec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!mem)
|
||||
return;
|
||||
printk_debug("head = %p last_rec = %p\n", head, last_rec);
|
||||
start = (unsigned long)head;
|
||||
end = (unsigned long)last_rec;
|
||||
printk_debug("start = 0x%08lx end = 0x%08lx\n", (unsigned long)start, (unsigned long)end);
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
/* Resize the right two memory areas so this table is in
|
||||
* a reserved area of memory. Everything has been carefully
|
||||
* setup so that is all we need to do.
|
||||
*/
|
||||
for(i = 0; i < entries; i++ ) {
|
||||
uint64_t map_start = mem->map[i].start;
|
||||
uint64_t map_end = map_start + mem->map[i].size;
|
||||
/* Does this area need to be expanded? */
|
||||
if (map_end == start) {
|
||||
mem->map[i].size = end - map_start;
|
||||
}
|
||||
/* Does this area need to be contracted? */
|
||||
else if (map_start == start) {
|
||||
mem->map[i].start = end;
|
||||
mem->map[i].size = map_end - end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long lb_table_fini(struct lb_header *head)
|
||||
{
|
||||
struct lb_record *rec, *first_rec;
|
||||
rec = lb_last_record(head);
|
||||
if (head->table_entries) {
|
||||
head->table_bytes += rec->size;
|
||||
}
|
||||
lb_reserve_table_memory(head);
|
||||
first_rec = lb_first_record(head);
|
||||
head->table_checksum = compute_ip_checksum(first_rec, head->table_bytes);
|
||||
head->header_checksum = 0;
|
||||
head->header_checksum = compute_ip_checksum(head, sizeof(*head));
|
||||
printk_debug("Write linuxbios table at: %p - %p\n",
|
||||
head, rec);
|
||||
return (unsigned long)rec;
|
||||
}
|
||||
|
||||
unsigned long setup_memory_table(
|
||||
struct lb_memory *mem,
|
||||
unsigned long totalram,
|
||||
unsigned long low_table_start, unsigned long low_table_end)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long write_linuxbios_table(
|
||||
unsigned long *processor_map,
|
||||
unsigned long totalram,
|
||||
unsigned long low_table_start, unsigned long low_table_end,
|
||||
unsigned long rom_table_start, unsigned long rom_table_end)
|
||||
{
|
||||
struct lb_header *head;
|
||||
struct lb_memory *mem;
|
||||
|
||||
head = lb_table_init(low_table_end);
|
||||
low_table_end = (unsigned long)head;
|
||||
|
||||
mem = lb_memory(head);
|
||||
/* Reserve our tables in low memory */
|
||||
lb_memory_range(mem, LB_MEM_RESERVED, low_table_start, low_table_end - low_table_start);
|
||||
lb_memory_range(mem, LB_MEM_RAM, low_table_end, 640*1024 - low_table_end);
|
||||
/* Reserve the whole dos BIOS reserved area, we can probably do
|
||||
* better but it isn't too important right now
|
||||
*/
|
||||
lb_memory_range(mem, LB_MEM_RESERVED, 0x000a0000, 0x00060000);
|
||||
/* Now show all of memory */
|
||||
lb_memory_range(mem, LB_MEM_RAM, 0x00100000, (totalram - 1024) << 10);
|
||||
|
||||
low_table_end = lb_table_fini(head);
|
||||
return low_table_end;
|
||||
}
|
||||
|
|
@ -38,9 +38,9 @@ void check_pirq_routing_table(void);
|
|||
#endif
|
||||
|
||||
#if defined(HAVE_PIRQ_TABLE)
|
||||
void copy_pirq_routing_table(void);
|
||||
unsigned long copy_pirq_routing_table(unsigned long start);
|
||||
#else
|
||||
#define copy_pirq_routing_table() do {} while(0)
|
||||
#define copy_pirq_routing_table(start) (start)
|
||||
#endif
|
||||
|
||||
#endif /* ARCH_PIRQ_ROUTING_H */
|
||||
|
|
|
|||
|
|
@ -264,8 +264,8 @@ void smp_write_compatibility_address_space(struct mp_config_table *mc,
|
|||
unsigned char busid, unsigned char address_modifier,
|
||||
unsigned int range_list);
|
||||
unsigned char smp_compute_checksum(void *v, int len);
|
||||
void smp_write_floating_table(void *v);
|
||||
void write_smp_table(void *v, unsigned long *processor_map);
|
||||
void *smp_write_floating_table(unsigned long addr);
|
||||
unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map);
|
||||
|
||||
/* A table (per mainboard) listing the initial apicid of each cpu. */
|
||||
extern unsigned long initial_apicid[MAX_CPUS];
|
||||
|
|
@ -273,7 +273,7 @@ extern unsigned long initial_apicid[MAX_CPUS];
|
|||
#else /* HAVE_MP_TABLE */
|
||||
#define CPU_ENABLED 1 /* Processor is available */
|
||||
#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */
|
||||
#define write_smp_table(v,p) do {} while(0)
|
||||
#define write_smp_table(v,p) ({ p; v; })
|
||||
#endif /* HAVE_MP_TABLE */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ static char rcsid[] = "$Id$";
|
|||
#include <arch/ioapic.h>
|
||||
#include <smp/atomic.h>
|
||||
#include <arch/smp/mpspec.h>
|
||||
#include <boot/linuxbios_table.h>
|
||||
|
||||
|
||||
/* The processor map.
|
||||
|
|
@ -157,6 +158,36 @@ static void wait_for_other_cpus(void)
|
|||
#define wait_for_other_cpus() do {} while(0)
|
||||
#endif /* SMP */
|
||||
|
||||
void write_tables(unsigned long totalram)
|
||||
{
|
||||
unsigned long low_table_start, low_table_end;
|
||||
unsigned long rom_table_start, rom_table_end;
|
||||
|
||||
rom_table_start = 0xf0000;
|
||||
rom_table_end = 0xf0000;
|
||||
/* Start low addr at 16 bytes instead of 0 because of a buglet
|
||||
* in the generic linux bunzip code, as it tests for the a20 line.
|
||||
*/
|
||||
low_table_start = 0;
|
||||
low_table_end = 16;
|
||||
|
||||
post_code(0x9a);
|
||||
check_pirq_routing_table();
|
||||
/* This table must be betweeen 0xf0000 & 0x100000 */
|
||||
rom_table_end = copy_pirq_routing_table(rom_table_end);
|
||||
|
||||
/* copy the smp block to address 0 */
|
||||
post_code(0x96);
|
||||
/* The smp table must be in 0-1K, 639K-640K, or 960K-1M */
|
||||
low_table_end = write_smp_table(low_table_end, processor_map);
|
||||
|
||||
/* The linuxbios table must be in 0-1K or 960K-1M */
|
||||
write_linuxbios_table(
|
||||
processor_map, totalram,
|
||||
low_table_start, low_table_end,
|
||||
rom_table_start, rom_table_end);
|
||||
}
|
||||
|
||||
void hardwaremain(int boot_complete)
|
||||
{
|
||||
/* Processor ID of the BOOT cpu (i.e. the one running this code) */
|
||||
|
|
@ -266,10 +297,7 @@ void hardwaremain(int boot_complete)
|
|||
|
||||
pci_zero_irq_settings();
|
||||
|
||||
check_pirq_routing_table();
|
||||
copy_pirq_routing_table();
|
||||
|
||||
post_code(0x9a);
|
||||
|
||||
/* to do: intel_serial_on(); */
|
||||
|
||||
|
|
@ -285,9 +313,11 @@ void hardwaremain(int boot_complete)
|
|||
/* make certain we are the only cpu running in linuxBIOS */
|
||||
wait_for_other_cpus();
|
||||
|
||||
/* copy the smp block to address 0 */
|
||||
post_code(0x96);
|
||||
write_smp_table((void *)16, processor_map);
|
||||
/* Now that we have collected all of our information
|
||||
* write our configuration tables.
|
||||
*/
|
||||
write_tables(totalram);
|
||||
|
||||
|
||||
#ifdef LINUXBIOS
|
||||
printk_info("Jumping to linuxbiosmain()...\n");
|
||||
|
|
|
|||
|
|
@ -53,11 +53,16 @@ void check_pirq_routing_table(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define RTABLE_DEST 0xf0000
|
||||
|
||||
void copy_pirq_routing_table(void)
|
||||
unsigned long copy_pirq_routing_table(unsigned long addr)
|
||||
{
|
||||
/* Align the table to be 16 byte aligned. */
|
||||
addr += 15;
|
||||
addr &= ~15;
|
||||
|
||||
/* This table must be betweeen 0xf0000 & 0x100000 */
|
||||
printk_info("Copying IRQ routing tables...");
|
||||
memcpy((char *) RTABLE_DEST, &intel_irq_routing_table, intel_irq_routing_table.size);
|
||||
memcpy((void *)addr, &intel_irq_routing_table, intel_irq_routing_table.size);
|
||||
printk_info("done.\n");
|
||||
|
||||
return addr + intel_irq_routing_table.size;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,15 @@ unsigned char smp_compute_checksum(void *v, int len)
|
|||
return checksum;
|
||||
}
|
||||
|
||||
void smp_write_floating_table(void *v)
|
||||
void *smp_write_floating_table(unsigned long addr)
|
||||
{
|
||||
struct intel_mp_floating *mf;
|
||||
void *v;
|
||||
|
||||
/* 16 byte align the table address */
|
||||
addr += 15;
|
||||
addr &= ~15;
|
||||
v = (void *)addr;
|
||||
|
||||
mf = v;
|
||||
mf->mpf_signature[0] = '_';
|
||||
|
|
@ -41,6 +47,7 @@ void smp_write_floating_table(void *v)
|
|||
mf->mpf_feature4 = 0;
|
||||
mf->mpf_feature5 = 0;
|
||||
mf->mpf_checksum = smp_compute_checksum(mf, mf->mpf_length*16);
|
||||
return v;
|
||||
}
|
||||
|
||||
void *smp_next_mpc_entry(struct mp_config_table *mc)
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
object uniform_boot.o
|
||||
|
|
@ -390,6 +390,11 @@ typedef Elf64_Phdr Elf_phdr;
|
|||
#endif
|
||||
|
||||
extern int elf_check_arch(Elf_ehdr *ehdr);
|
||||
extern void jmp_to_elf_entry(void *entry, void *ube);
|
||||
extern int elfboot(size_t totalram);
|
||||
extern void jmp_to_elf_entry(void *entry);
|
||||
extern int elfboot(void);
|
||||
|
||||
#define FIRMWARE_TYPE "LinuxBIOS"
|
||||
#define BOOTLOADER "elfboot"
|
||||
#define BOOTLOADER_VERSION "0.99999"
|
||||
|
||||
#endif /* elf.h */
|
||||
|
|
|
|||
89
src/include/boot/elf_boot.h
Normal file
89
src/include/boot/elf_boot.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef ELF_BOOT_H
|
||||
#define ELF_BOOT_H
|
||||
|
||||
#include <stdint.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_HEAD_SIZE (8*1024)
|
||||
#define ELF_BOOT_MAGIC 0x0E1FB007
|
||||
|
||||
typedef uint16_t Elf_Half;
|
||||
typedef uint32_t Elf_Word;
|
||||
typedef uint64_t Elf_Xword;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf_Word b_signature; /* "0x0E1FB007" */
|
||||
Elf_Word b_size;
|
||||
Elf_Half b_checksum;
|
||||
Elf_Half b_records;
|
||||
} Elf_Bhdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
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;
|
||||
|
||||
|
||||
/* For standard notes n_namesz must be zero */
|
||||
/* All of the following standard note types provide a single null
|
||||
* terminated string in the descriptor.
|
||||
*/
|
||||
#define EBN_FIRMWARE_TYPE 0x00000001
|
||||
/* On platforms that support multiple classes of firmware this field
|
||||
* specifies the class of firmware you are loaded under.
|
||||
*/
|
||||
#define EBN_BOOTLOADER_NAME 0x00000002
|
||||
/* This specifies just the name of the bootloader for easy comparison */
|
||||
#define EBN_BOOTLOADER_VERSION 0x00000003
|
||||
/* This specifies the version of the bootlader */
|
||||
#define EBN_COMMAND_LINE 0x00000004
|
||||
/* This specifies a command line that can be set by user interaction,
|
||||
* and is provided as a free form string to the loaded image.
|
||||
*/
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
|
||||
/* Linux image notes for booting... The name for all of these is Linux */
|
||||
|
||||
#define LINUX_NOTE_BOOT "Linux"
|
||||
|
||||
#define LIN_COMMAND_LINE 0x00000001
|
||||
/* The command line to pass to the loaded kernel. */
|
||||
#define LIN_ROOT_DEV 0x00000002
|
||||
/* The root dev to pass to the loaded kernel. */
|
||||
#define LIN_RAMDISK_FLAGS 0x00000003
|
||||
/* Various old ramdisk flags */
|
||||
#define LIN_INITRD_START 0x00000004
|
||||
/* Start of the ramdisk in bytes */
|
||||
#define LIN_INITRD_SIZE 0x00000005
|
||||
/* Size of the ramdisk in bytes */
|
||||
|
||||
|
||||
#endif /* ELF_BOOT_H */
|
||||
23
src/include/boot/linuxbios_table.h
Normal file
23
src/include/boot/linuxbios_table.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef LINUXBIOS_TABLE_H
|
||||
#define LINUXBIOS_TABLE_H
|
||||
|
||||
#include <boot/linuxbios_tables.h>
|
||||
|
||||
/* This file holds function prototypes for building the linuxbios table. */
|
||||
unsigned long write_linuxbios_table(
|
||||
unsigned long *processor_map,
|
||||
unsigned long totalram,
|
||||
unsigned long low_table_start, unsigned long low_table_end,
|
||||
unsigned long rom_table_start, unsigned long rom_table_end);
|
||||
|
||||
struct lb_header *lb_table_init(unsigned long addr);
|
||||
struct lb_record *lb_first_record(struct lb_header *header);
|
||||
struct lb_record *lb_last_record(struct lb_header *header);
|
||||
struct lb_record *lb_next_record(struct lb_record *rec);
|
||||
struct lb_record *lb_new_record(struct lb_header *header);
|
||||
struct lb_memory *lb_memory(struct lb_header *header);
|
||||
void lb_memory_range(struct lb_memory *mem,
|
||||
uint32_t type, unsigned long start, unsigned long size);
|
||||
unsigned long lb_table_fini(struct lb_header *header);
|
||||
|
||||
#endif /* LINUXBIOS_TABLE_H */
|
||||
83
src/include/boot/linuxbios_tables.h
Normal file
83
src/include/boot/linuxbios_tables.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#ifndef LINUXBIOS_TABLES_H
|
||||
#define LINUXBIOS_TABLES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* The linuxbios table information is for conveying information
|
||||
* from the firmware to the loaded OS image. Primarily this
|
||||
* is expected to be information that cannot be discovered by
|
||||
* other means, such as quering the hardware directly.
|
||||
*
|
||||
* All of the information should be Position Independent Data.
|
||||
* That is it should be safe to relocated any of the information
|
||||
* without it's meaning/correctnes changing. For table that
|
||||
* can reasonably be used on multiple architectures the data
|
||||
* size should be fixed. This should ease the transition between
|
||||
* 32 bit and 64 bit architectures etc.
|
||||
*
|
||||
* The completeness test for the information in this table is:
|
||||
* - Can all of the hardware be detected?
|
||||
* - Are the per motherboard constants available?
|
||||
* - Is there enough to allow a kernel to run that was written before
|
||||
* a particular motherboard is constructed? (Assuming the kernel
|
||||
* has drivers for all of the hardware but it does not have
|
||||
* assumptions on how the hardware is connected together).
|
||||
*
|
||||
* With this test it should be straight forward to determine if a
|
||||
* table entry is required or not. This should remove much of the
|
||||
* long term compatibility burden as table entries which are
|
||||
* irrelevant or have been replaced by better alternatives may be
|
||||
* dropped. Of course it is polite and expidite to include extra
|
||||
* table entries and be backwards compatible, but it is not required.
|
||||
*/
|
||||
|
||||
|
||||
struct lb_header
|
||||
{
|
||||
uint8_t signature[4]; /* LBIO */
|
||||
uint32_t header_bytes;
|
||||
uint32_t header_checksum;
|
||||
uint32_t table_bytes;
|
||||
uint32_t table_checksum;
|
||||
uint32_t table_entries;
|
||||
};
|
||||
|
||||
/* Every entry in the boot enviroment list will correspond to a boot
|
||||
* info record. Encoding both type and size. The type is obviously
|
||||
* so you can tell what it is. The size allows you to skip that
|
||||
* boot enviroment record if you don't know what it easy. This allows
|
||||
* forward compatibility with records not yet defined.
|
||||
*/
|
||||
struct lb_record {
|
||||
uint32_t tag; /* tag ID */
|
||||
uint32_t size; /* size of record (in bytes) */
|
||||
};
|
||||
|
||||
#define LB_TAG_UNUSED 0x0000
|
||||
|
||||
#define LB_TAG_MEMORY 0x0001
|
||||
|
||||
struct lb_memory_range {
|
||||
uint64_t start;
|
||||
uint64_t size;
|
||||
uint32_t type;
|
||||
#define LB_MEM_RAM 1
|
||||
#define LB_MEM_RESERVED 2
|
||||
|
||||
};
|
||||
|
||||
struct lb_memory {
|
||||
uint32_t tag;
|
||||
uint32_t size;
|
||||
struct lb_memory_range map[0];
|
||||
};
|
||||
|
||||
#define LB_TAG_HWRPB 0x0002
|
||||
struct lb_hwrpb {
|
||||
uint32_t tag;
|
||||
uint32_t size;
|
||||
uint64_t hwrpb;
|
||||
};
|
||||
|
||||
|
||||
#endif /* LINUXBIOS_TABLES_H */
|
||||
6
src/include/ip_checksum.h
Normal file
6
src/include/ip_checksum.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef IP_CHECKSUM_H
|
||||
#define IP_CHECKSUM_H
|
||||
|
||||
unsigned long compute_ip_checksum(void *addr, unsigned long length);
|
||||
|
||||
#endif /* IP_CHECKSUM_H */
|
||||
|
|
@ -16,3 +16,4 @@ object do_inflate.o
|
|||
object floppy_subr.o
|
||||
object delay.o
|
||||
object fallback_boot.o USE_FALLBACK_BOOT
|
||||
object compute_ip_checksum.o
|
||||
20
src/lib/compute_ip_checksum.c
Normal file
20
src/lib/compute_ip_checksum.c
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#include <ip_checksum.h>
|
||||
|
||||
unsigned long compute_ip_checksum(void *addr, unsigned long length)
|
||||
{
|
||||
unsigned short *ptr;
|
||||
unsigned long sum;
|
||||
unsigned long len;
|
||||
/* Assumes len is a multiple of two, and addr is 2 byte aligned. */
|
||||
/* compute an ip style checksum */
|
||||
sum = 0;
|
||||
len = length >> 1;
|
||||
ptr = addr;
|
||||
while (len--) {
|
||||
sum += *(ptr++);
|
||||
if (sum > 0xFFFF)
|
||||
sum -= 0xFFFF;
|
||||
}
|
||||
return (~sum) & 0xFFFF;
|
||||
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#include <printk.h>
|
||||
#include <part/fallback_boot.h>
|
||||
#include <boot/elf.h>
|
||||
#include <boot/uniform_boot.h>
|
||||
#include <boot/elf_boot.h>
|
||||
#include <rom/read_bytes.h>
|
||||
#include <string.h>
|
||||
#include <subr.h>
|
||||
|
|
@ -57,7 +57,7 @@ static int safe_range(unsigned long start, unsigned long len)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int elfboot(size_t totalram)
|
||||
int elfboot(void)
|
||||
{
|
||||
static unsigned char header[ELF_HEAD_SIZE];
|
||||
unsigned long offset;
|
||||
|
|
@ -68,15 +68,14 @@ int elfboot(size_t totalram)
|
|||
int i;
|
||||
|
||||
printk_info("\n");
|
||||
printk_info("Welcome to elfboot, the open sourced starter.\n");
|
||||
printk_info("Febuary 2001, Eric Biederman.\n");
|
||||
printk_info("Version 0.9999\n");
|
||||
printk_info("Welcome to %s, the open sourced starter.\n", BOOTLOADER);
|
||||
printk_info("January 2002, Eric Biederman.\n");
|
||||
printk_info("Version %s\n", BOOTLOADER_VERSION);
|
||||
printk_info("\n");
|
||||
if (streams->init() < 0) {
|
||||
printk_err("Could not initialize driver...\n");
|
||||
goto out;
|
||||
}
|
||||
ptr = get_ube_pointer(totalram);
|
||||
|
||||
post_code(0xf8);
|
||||
/* Read in the initial ELF_HEAD_SIZE bytes */
|
||||
|
|
@ -228,7 +227,7 @@ int elfboot(size_t totalram)
|
|||
post_code(0xfe);
|
||||
|
||||
/* Jump to kernel */
|
||||
jmp_to_elf_entry(entry, ptr);
|
||||
jmp_to_elf_entry(entry);
|
||||
|
||||
out:
|
||||
printk_err("Bad ELF Image\n");
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ int linuxbiosmain(unsigned long base, unsigned long totalram)
|
|||
#endif /* USE_TFTP */
|
||||
|
||||
#if USE_ELF_BOOT
|
||||
return elfboot(totalram);
|
||||
return elfboot();
|
||||
#else /* !ELF_BOOT */
|
||||
printk_info("\n");
|
||||
printk_info("Welcome to start32, the open sourced starter.\n");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include <string.h>
|
||||
#include <printk.h>
|
||||
|
||||
void smp_write_config_table(void *v, unsigned long * processor_map)
|
||||
void *smp_write_config_table(void *v, unsigned long * processor_map)
|
||||
{
|
||||
int ioapicid = 0;
|
||||
static const char sig[4] = "PCMP";
|
||||
|
|
@ -120,12 +120,14 @@ void smp_write_config_table(void *v, unsigned long * processor_map)
|
|||
mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
|
||||
printk_debug("Wrote the mp table end at: %p - %p\n",
|
||||
mc, smp_next_mpe_entry(mc));
|
||||
return smp_next_mpe_entry(mc);
|
||||
}
|
||||
|
||||
void write_smp_table(void *v, unsigned long *processor_map)
|
||||
unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map)
|
||||
{
|
||||
smp_write_floating_table(v);
|
||||
smp_write_config_table(v, processor_map);
|
||||
void *v;
|
||||
v = smp_write_floating_table(addr);
|
||||
return (unsigned long)smp_write_config_table(v, processor_map);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ nooption USE_DEFAULT_LAYOUT
|
|||
option STACK_SIZE=0x2000
|
||||
option USE_FALLBACK_BOOT=1
|
||||
|
||||
option USE_RAMTEST=1
|
||||
dir /src/ram
|
||||
#option USE_RAMTEST=1
|
||||
#dir /src/ram
|
||||
|
||||
#/* falback */
|
||||
option ZKERNEL_START=0xffff0000
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ void cache_ram_start(void)
|
|||
|
||||
init_memory();
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
{
|
||||
unsigned long addr;
|
||||
for(addr = 0; addr < 0x20000000; addr += 0x02000000) {
|
||||
|
|
@ -97,6 +97,7 @@ void cache_ram_start(void)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
error |= ramcheck(0x00000000, 0x00080000, 20);
|
||||
error |= ramcheck(0x02000000, 0x02080000, 20);
|
||||
error |= ramcheck(0x04000000, 0x04080000, 20);
|
||||
|
|
@ -114,13 +115,14 @@ void cache_ram_start(void)
|
|||
error |= ramcheck(0x1a000000, 0x1a080000, 20);
|
||||
error |= ramcheck(0x1c000000, 0x1c080000, 20);
|
||||
error |= ramcheck(0x1e000000, 0x1e080000, 20);
|
||||
#endif
|
||||
#if 0
|
||||
error |= ramcheck(0x00000000, 0x00080000, 20);
|
||||
#endif
|
||||
#if 1
|
||||
#if 0
|
||||
display_rdram_regs(rdram_chips );
|
||||
#endif
|
||||
#if 1
|
||||
#if 0
|
||||
display_mch_regs();
|
||||
#endif
|
||||
if (error) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include <string.h>
|
||||
#include <printk.h>
|
||||
|
||||
void smp_write_config_table(void *v, unsigned long * processor_map)
|
||||
void *smp_write_config_table(void *v, unsigned long * processor_map)
|
||||
{
|
||||
int ioapicid = 0;
|
||||
static const char sig[4] = "PCMP";
|
||||
|
|
@ -125,12 +125,14 @@ void smp_write_config_table(void *v, unsigned long * processor_map)
|
|||
mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
|
||||
printk_debug("Wrote the mp table end at: %p - %p\n",
|
||||
mc, smp_next_mpe_entry(mc));
|
||||
return smp_next_mpe_entry(mc);
|
||||
}
|
||||
|
||||
void write_smp_table(void *v, unsigned long *processor_map)
|
||||
unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map)
|
||||
{
|
||||
smp_write_floating_table(v);
|
||||
smp_write_config_table(v, processor_map);
|
||||
void *v;
|
||||
v = smp_write_floating_table(addr);
|
||||
return (unsigned long)smp_write_config_table(v, processor_map);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include <printk.h>
|
||||
#include <cpu/p6/apic.h>
|
||||
|
||||
void smp_write_config_table(void *v, unsigned long * processor_map)
|
||||
void *smp_write_config_table(void *v, unsigned long * processor_map)
|
||||
{
|
||||
static const char sig[4] = "PCMP";
|
||||
static const char oem[8] = "TYAN ";
|
||||
|
|
@ -145,13 +145,15 @@ void smp_write_config_table(void *v, unsigned long * processor_map)
|
|||
mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
|
||||
printk_debug("Wrote the mp table end at: %p - %p\n",
|
||||
mc, smp_next_mpe_entry(mc));
|
||||
return smp_next_mpe_entry(mc);
|
||||
}
|
||||
|
||||
void write_smp_table(void *v, unsigned long *processor_map)
|
||||
unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map)
|
||||
{
|
||||
void *v;
|
||||
printk_debug("Writing the mp table\n");
|
||||
smp_write_floating_table(v);
|
||||
smp_write_config_table(v, processor_map);
|
||||
v = smp_write_floating_table(addr);
|
||||
return (unsigned long)smp_write_config_table(v, processor_map);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue