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:
Eric W. Biederman 2002-01-08 07:04:35 +00:00
commit 9cda94e6d2
32 changed files with 3383 additions and 117 deletions

View file

@ -1 +1,2 @@
object boot.o
object linuxbios_table.o

View file

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

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

View file

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

View file

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

View file

@ -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");

View file

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

View file

@ -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)