nitial checkin

This commit is contained in:
Steven James 2002-11-12 16:46:25 +00:00
commit 504a78151b
10 changed files with 540 additions and 0 deletions

10
util/baremetal/Makefile Normal file
View file

@ -0,0 +1,10 @@
CC = gcc
CFLAGS = -I include -O2
DEPS = bootselect.o rom_fill_inbuf.o chooser.o lib/baremetal.a
bootselect.elf: $(DEPS)
ld -defsym HEAPSIZE=0 -T elfImage.lds $(DEPS) -o bootselect.elf
clean:
rm bootselect.elf *.o

28
util/baremetal/README Normal file
View file

@ -0,0 +1,28 @@
This is the bare metal toolkit for LinuxBIOS.
It was produced and is maintained by Steven James <pyro@linuxlabs.com>
It's purpose is to simplify development of standalone ELF executables suitable
as a payload for LinuxBIOS. Two examples are included, hello and bootselect.
Most of this toolkit comes from LinuxBIOS itself. A few pieces are borrowed
from Etherboot (such as code to locate and use the LinuxBIOS table).
It is important to note that even though the main part is a Library, Since
it is built from GPL code, it falls under GPL, not LGPL. This may matter to
you in production since that means your project will also need to be GPL in
order to be linked with this toolkit.
This is an early release. It has been used successfully to produce several
payloads. However, as it is an early release, if you intend to use the payloads
in production, it may be best to maintain your own production snapshot for a bit.
Hello is a simple example program. All it does is say hello, then you
hit reset :-)
Bootselect allows for multiple choice payloads. It scans the flash ROM
for tagged executable images and checks to see if a character is waiting on the
serial console. If not, the first image is run immediatly. If a character is
waiting, it is dropped, a list of tagged images is presented. The user selects
the image by number. This can come in quite handy for testing, or for loading
diagnostic and other secondary firmware.

3
util/baremetal/TODO Normal file
View file

@ -0,0 +1,3 @@
1. Figure out why the trick of moving out of the way when loading a new ELF
image is failing

View file

@ -0,0 +1,14 @@
ARCH = i386
CC = gcc
CFLAGS = -I ../include -I ../include/$(ARCH) -O2
DEPS = bootselect.o rom_fill_inbuf.o chooser.o ../lib/baremetal.a
bootselect.elf: $(DEPS)
ld -defsym HEAPSIZE=0x8000 -T elfImage.lds $(DEPS) -o bootselect.elf
clean:
rm bootselect.elf *.o

View file

@ -0,0 +1,3 @@
Add support for gzipped target
Add support for other stream types such as IDE

View file

@ -0,0 +1,50 @@
/************************************************************************
*
* bootselect.c
* A standalone rom image selector for LinuxBIOS
*
* Copyright 2002 Steven James <pyro@linuxlabs.com> and LinuxLabs
* http://www.linuxlabs.com
*
* Licensed under the GNU General Public License (GPL) v2 or later
*
**********************************************************************/
#include <arch/io.h>
#include <printk.h>
#include <rom/read_bytes.h>
#include <boot/elf.h>
#define DPRINTF( x... )
//#define DPRINTF printk
extern struct lb_memory *get_lbmem(void);
char buffer[16];
extern struct stream rom_stream;
struct lb_memory *lbmem;
int main(void) {
int blocks;
while(1) {
printk("Welcome to the LinuxLabs boot chooser!\n");
lbmem = get_lbmem();
DPRINTF("Got lbmem struct: %08x\n", (unsigned int) lbmem);
if(choose_stream(&rom_stream) <0)
return(-1);
elfboot(&rom_stream, lbmem);
}
outb(0x0e, 0x3f9);
}

View file

@ -0,0 +1,76 @@
/************************************************************************
*
* bootselect.c
* A standalone rom image selector for LinuxBIOS
*
* Copyright 2002 Steven James <pyro@linuxlabs.com> and LinuxLabs
* http://www.linuxlabs.com
*
* Licensed under the GNU General Public License (GPL) v2 or later
*
**********************************************************************/
#include <rom/read_bytes.h>
#include <string.h>
#include <stdlib.h>
#include <printk.h>
#include <serial_subr.h>
int choose_stream(struct stream *stream)
{
int stream_count, i,j;
tag_head *directory, *current;
if(stream->init() < 0) {
printk_err("could not init stream. This is bad!\n");
return(-1);
}
if(!stream->init_tags)
return(0);
stream_count = stream->init_tags();
if(!stream_count)
return(0);
current = directory = malloc(stream_count * sizeof(tag_head));
printk_info("Stream count = %u blocks\n", stream_count);
stream->get_tags(directory);
j=0;
for(i=stream_count; i>0;) {
current->data[5 + current->block_count*16] = 0;
// printk_info("TAG: block_count = %u, current = %08x\n", current->block_count, (unsigned int ) current);
printk_info("STREAM: %u. %s\n", j++, current->data);
i -= current->block_count;
i--;
current += current->block_count+1;
}
j=0;
if(iskey()) {
j = ttys0_rx_char();
j=-1;
while(j<0) {
printk_info("Choose a stream: ");
j = ttys0_rx_char();
if(j == 0x1b || j == 'x')
return(-1);
if(j <0x30 || j> 0x39) {
printk_info(" INVALID RESPONSE\n");
j=-1;
} else
j-=0x30;
}
}
stream->load_tag(j);
return(0);
}

View file

@ -0,0 +1,58 @@
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
HEAPSIZE = DEFINED(HEAPSIZE) ? HEAPSIZE : 0x8000;
ENTRY(main)
SECTIONS
{
/* . = 0x10000 - (elf_note - elf_header); */
. = 0x1000;
_text = .; /* Text and read-only data */
.text . : {
*(.text)
*(.fixup)
*(.gnu.warning)
} = 0x9090
.rodata (.): { *(.rodata) }
.kstrtab (.): { *(.kstrtab) }
. = ALIGN(16); /* Exception table */
_etext = .; /* End of text section */
.data (.): { /* Data */
*(.data)
CONSTRUCTORS
}
_edata = .; /* End of data section */
__bss_start = .; /* BSS */
.bss (.): {
*(.bss)
}
_ebss = .;
_heap = .;
.heap (.): {
. = HEAPSIZE;
}
_eheap = .;
_end = . ;
_ram_seg = _text;
_eram_seg = _end;
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}

View file

@ -0,0 +1,227 @@
/*
* Modified from LinuxBIOS by Steven James <pyro@linuxlabs.com>
*
*/
#include <printk.h>
#include <stdlib.h>
#include <subr.h>
#include <stddef.h>
#include <rom/read_bytes.h>
#include <string.h>
#ifndef ZKERNEL_START
#define ZKERNEL_START 0xfff00000
#endif
#ifndef ZKERNEL_MASK
#define ZKERNEL_MASK 0x0000ffff
#endif
#ifndef _ROMTOP
#define _ROMTOP 0xfffffff0
#endif
/* The inbuf copy option has been killed... */
#define K64 (64 * 1024)
static unsigned char *zkernel_start = (unsigned char *)ZKERNEL_START;
static unsigned long zkernel_mask = ZKERNEL_MASK;
static unsigned char *nvram;
static int block_count;
static int block_offset;
static unsigned int max_block = (_ROMTOP - ZKERNEL_START)/K64;
static int init_bytes(void);
int rom_seek(unsigned long int where)
{
block_count = where / K64;
block_offset = where - (block_count * K64);
nvram = zkernel_start + (K64 * block_count);
return(where);
}
static void fini_bytes(void)
{
return;
}
static byte_offset_t rom_read_bytes(int cp, void *vdest, byte_offset_t count)
{
unsigned char *dest = vdest;
byte_offset_t bytes = 0;
while (bytes < count) {
int length;
if (block_offset == K64) {
block_offset = 0;
block_count++;
nvram+= K64;
}
if (block_count > max_block) {
printk_emerg( "%6d:%s() - overflowed source buffer. max_block = %u\n",
__LINE__, __FUNCTION__, max_block);
return bytes;
}
length = K64 - block_offset;
if (length > (count - bytes)) {
length = count - bytes;
}
if (cp) {
memcpy(dest, nvram + block_offset, length);
}
dest += length;
block_offset += length;
bytes += length;
}
return bytes;
}
static byte_offset_t skip_bytes(byte_offset_t count)
{
return rom_read_bytes(0, 0, count);
}
static byte_offset_t read_bytes(void *vdest, byte_offset_t count)
{
return rom_read_bytes(1, vdest, count);
}
static int tag_count=0;
static int tag_blocks=0;
unsigned long tags[32];
void rom_load_tag(int tag)
{
tag_head current;
int i;
// printk_info("Loading tag %u @ %08x\n", tag, tags[tag]);
if(tag < tag_count) {
rom_seek( tags[tag] );
read_bytes(&current, sizeof(tag_head) );
// printk_info("Tag contents: ");
// for(i=0; i<16; i++)
// printk_info("%02x ", ( (char *) &current)[i] );
// printk_info("\n");
// printk_info("TAG block count = %u\n", current.block_count);
skip_bytes( current.block_count * sizeof(tag_head) );
}
}
int strncmp(char *subject, char *target, int count)
{
int i;
for(i=0; i<count; i++)
if(subject[i] != target[i])
break;
if(i==count)
return(0);
return(subject[i] - target[i]);
}
void rom_get_tags(void *buffer)
{
int i;
tag_head *ptr = buffer;
int count;
for(i=0; i<tag_count; i++) {
rom_seek(tags[i]);
read_bytes(ptr, sizeof(tag_head));
// printk_info("copying tag at %08x, with block_count=%u to %08x\n", tags[i], ptr->block_count, (int) ptr);
count = ptr->block_count;
ptr++;
if(count) {
read_bytes(ptr, sizeof(tag_head) * count);
ptr += count;
}
}
}
int search_tags(void)
{
tag_head current;
rom_seek(0);
tag_count=0;
tag_blocks=0;
// printk_info("Searching for %u byte tags\n", sizeof(tag_head) );
if(!tag_count) {
while( read_bytes(&current, sizeof(tag_head)) == sizeof(tag_head) ) {
if(strncmp(current.signature, "$TAG$", 5))
continue;
// we found a tag, now look at it
tag_blocks++;
tags[tag_count++] = K64 * block_count + block_offset - sizeof(tag_head);
// printk_info("Found tag at %08x block_count = %u\n", tags[tag_count-1], current.block_count);
if(current.block_count >0) {
skip_bytes( current.block_count * sizeof(tag_head) );
tag_blocks += current.block_count;
}
}
}
if(tag_count) {
rom_load_tag(0);
} else
rom_seek(0);
return(tag_blocks);
}
static int init_bytes(void)
{
int i;
block_count = 0;
block_offset = 0;
nvram = zkernel_start;
printk_debug("%6d:%s() - zkernel_start:0x%08x "
"zkernel_mask:0x%08x\n",
__LINE__, __FUNCTION__,
zkernel_start, zkernel_mask);
i = search_tags();
printk_info("init_bytes found %u tags\n", i);
return 0;
}
struct stream rom_stream = {
.init = init_bytes,
.init_tags = search_tags,
.get_tags = rom_get_tags,
.load_tag = rom_load_tag,
.read = read_bytes,
.skip = skip_bytes,
.fini = fini_bytes,
};

View file

@ -0,0 +1,71 @@
/* This setup assumes you have at least a 16M machine
* The problem is that with 2GB of RAM you use nearly 23M
* of memory in the kernel page tables, and since 2.2 doesn't check
* where the initrd is placed before allocating memory this is a
* problem. With a 8M Ramdisk + 23M kernel that is 31M leaving
* little room for things to grow.
* With the limit at 112M (i.e. 0x00700000) we should be o.k.)
*
* If you need to change the amount of assumed memory.
* The uppper.LENGTH needs to change so that
* upper.LENGTH + upper.ORIGIN = MEMORY_SIZE
* and the computation just before ramdisk placing also should
* be corrected, to be:
* . = MEMORY_SIZE - ((ramdisk_data_end - ramdisk_data) + 4095)
* .ramdisk(ALIGN(4096))
*/
/* INCLUDE mkelfImage.lds */
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
HEAPSIZE = DEFINED(HEAPSIZE) ? HEAPSIZE : 0x8000;
ENTRY(main)
SECTIONS
{
/* . = 0x10000 - (elf_note - elf_header); */
. = 0x1000;
_text = .; /* Text and read-only data */
.text . : {
*(.text)
*(.fixup)
*(.gnu.warning)
} = 0x9090
.rodata (.): { *(.rodata) }
.kstrtab (.): { *(.kstrtab) }
. = ALIGN(16); /* Exception table */
_etext = .; /* End of text section */
.data (.): { /* Data */
*(.data)
CONSTRUCTORS
}
_edata = .; /* End of data section */
__bss_start = .; /* BSS */
.bss (.): {
*(.bss)
}
_ebss = .;
_heap = .;
.heap (.): {
. = HEAPSIZE;
}
_eheap = .;
_end = . ;
_ram_seg = _text;
_eram_seg = _end;
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}