nitial checkin
This commit is contained in:
parent
f9deaf60c2
commit
504a78151b
10 changed files with 540 additions and 0 deletions
10
util/baremetal/Makefile
Normal file
10
util/baremetal/Makefile
Normal 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
28
util/baremetal/README
Normal 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
3
util/baremetal/TODO
Normal 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
|
||||
14
util/baremetal/bootselect/Makefile
Normal file
14
util/baremetal/bootselect/Makefile
Normal 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
|
||||
3
util/baremetal/bootselect/TODO
Normal file
3
util/baremetal/bootselect/TODO
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
Add support for gzipped target
|
||||
Add support for other stream types such as IDE
|
||||
50
util/baremetal/bootselect/bootselect.c
Normal file
50
util/baremetal/bootselect/bootselect.c
Normal 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);
|
||||
|
||||
}
|
||||
|
||||
76
util/baremetal/bootselect/chooser.c
Normal file
76
util/baremetal/bootselect/chooser.c
Normal 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);
|
||||
}
|
||||
58
util/baremetal/bootselect/elfImage.lds
Normal file
58
util/baremetal/bootselect/elfImage.lds
Normal 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) }
|
||||
}
|
||||
227
util/baremetal/bootselect/rom_fill_inbuf.c
Normal file
227
util/baremetal/bootselect/rom_fill_inbuf.c
Normal 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(¤t, sizeof(tag_head) );
|
||||
|
||||
// printk_info("Tag contents: ");
|
||||
// for(i=0; i<16; i++)
|
||||
// printk_info("%02x ", ( (char *) ¤t)[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(¤t, 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,
|
||||
};
|
||||
71
util/baremetal/elfImage.lds
Normal file
71
util/baremetal/elfImage.lds
Normal 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) }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue