coreboot-kgpe-d16/util/mkelfImage/linux-ia64/convert_params.c
Stefan Reinauer 14e2277962 Since some people disapprove of white space cleanups mixed in regular commits
while others dislike them being extra commits, let's clean them up once and
for all for the existing code. If it's ugly, let it only be ugly once :-)

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Stefan Reinauer <stepan@coresystems.de>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5507 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
2010-04-27 06:56:47 +00:00

334 lines
8.4 KiB
C

#include "stdint.h"
#include "limits.h"
#include <stdarg.h>
#include "elf.h"
#include "elf_boot.h"
#include "convert.h"
/* NOTE be very careful with static variables. No relocations are
* being performed so static variables with initialized pointers will
* point to the wrong locations, unless this file is loaded at just
* the right location.
*/
/* Data and functions in head.S */
extern void uart_tx_byte(int c);
static void putchar(int c)
{
if (c == '\n') {
putchar('\r');
}
#if 0
uart_tx_byte(c);
#endif
}
#define LONG_SHIFT ((int)((sizeof(unsigned long)*CHAR_BIT) - 4))
#define INT_SHIFT ((int)((sizeof(unsigned int)*CHAR_BIT) - 4))
#define SHRT_SHIFT ((int)((sizeof(unsigned short)*CHAR_BIT) - 4))
#define CHAR_SHIFT ((int)((sizeof(unsigned char)*CHAR_BIT) - 4))
/**************************************************************************
PRINTF and friends
Formats:
%x - 4 bytes int (8 hex digits, lower case)
%X - 4 bytes int (8 hex digits, upper case)
%lx - 8 bytes long (16 hex digits, lower case)
%lX - 8 bytes long (16 hex digits, upper case)
%hx - 2 bytes int (4 hex digits, lower case)
%hX - 2 bytes int (4 hex digits, upper case)
%hhx - 1 byte int (2 hex digits, lower case)
%hhX - 1 byte int (2 hex digits, upper case)
- optional # prefixes 0x or 0X
%d - decimal int
%c - char
%s - string
Note: width specification not supported
**************************************************************************/
static void printf(const char *fmt, ...)
{
va_list args;
char *p;
va_start(args, fmt);
for ( ; *fmt != '\0'; ++fmt) {
if (*fmt != '%') {
putchar(*fmt);
continue;
}
if (*++fmt == 's') {
for(p = va_arg(args, char *); *p != '\0'; p++)
putchar(*p);
}
else { /* Length of item is bounded */
char tmp[40], *q = tmp;
int shift = INT_SHIFT;
if (*fmt == 'l') {
shift = LONG_SHIFT;
fmt++;
}
else if (*fmt == 'h') {
shift = SHRT_SHIFT;
fmt++;
if (*fmt == 'h') {
shift = CHAR_SHIFT;
fmt++;
}
}
/*
* Before each format q points to tmp buffer
* After each format q points past end of item
*/
if ((*fmt | 0x20) == 'x') {
/* With x86 gcc, sizeof(long) == sizeof(int) */
unsigned long h;
int ncase;
if (shift > INT_SHIFT) {
h = va_arg(args, unsigned long);
} else {
h = va_arg(args, unsigned int);
}
ncase = (*fmt & 0x20);
for ( ; shift >= 0; shift -= 4)
*q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
}
else if (*fmt == 'd') {
char *r;
long i;
if (shift > INT_SHIFT) {
i = va_arg(args, long);
} else {
i = va_arg(args, int);
}
if (i < 0) {
*q++ = '-';
i = -i;
}
p = q; /* save beginning of digits */
do {
*q++ = '0' + (i % 10);
i /= 10;
} while (i);
/* reverse digits, stop in middle */
r = q; /* don't alter q */
while (--r > p) {
i = *r;
*r = *p;
*p++ = i;
}
}
else if (*fmt == 'c')
*q++ = va_arg(args, int);
else
*q++ = *fmt;
/* now output the saved string */
for (p = tmp; p < q; ++p)
putchar(*p);
}
}
va_end(args);
}
void *memcpy(void *vdest, void *vsrc, size_t size)
{
unsigned char *dest = vdest, *src = vsrc;
size_t i;
for(i = 0; i < size; i++) {
*dest++ = *src++;
}
return dest;
}
int memcmp(void *vs1, void *vs2, size_t size)
{
unsigned char *s1 =vs1, *s2=vs2;
size_t i;
for(i = 0; i < size; i++, s1++, s2++) {
if (*s1 != *s2)
return *s1 - *s2;
}
return 0;
}
void strappend(char *dest, const char *src, size_t max)
{
size_t len, i;
/* Walk to the end of the destination string */
for(len = 0; len < max; len++) {
if (dest[len] == '\0')
break;
}
/* Walk through the source string and append it */
for(i = 0; (i + len) < max; i++) {
if (src[i] == '\0')
break;
dest[len + i] = src[i];
}
len = len + i;
/* Now null terminate the string */
if (len >= max) {
len = max -1;
}
dest[len] = '\0';
}
static struct ia64_boot_param {
uint64_t command_line; /* physical address of command line arguments */
uint64_t efi_systab; /* physical address of EFI system table */
uint64_t efi_memmap; /* physical address of EFI memory map */
uint64_t efi_memmap_size; /* size of EFI memory map */
uint64_t efi_memdesc_size; /* size of an EFI memory map descriptor */
uint32_t efi_memdesc_version; /* memory descriptor version */
struct {
uint16_t num_cols; /* number of columns on console output device */
uint16_t num_rows; /* number of rows on console output device */
uint16_t orig_x; /* cursor's x position */
uint16_t orig_y; /* cursor's y position */
} console_info;
uint64_t fpswa; /* physical address of the fpswa interface */
uint64_t initrd_start;
uint64_t initrd_size;
} bp = { 0, 0, 0, 0, 0, 0, { 80, 24, 0, 0 }, 0, 0, 0 };
static void append_command_line(char *arg)
{
strappend((char *)bp.command_line, " ", CMDLINE_MAX);
strappend((char *)bp.command_line, arg, CMDLINE_MAX);
}
static void convert_ia64_boot_params(struct ia64_boot_param *orig_bp)
{
/* Copy the parameters I have no clue about */
bp.efi_systab = orig_bp->efi_systab;
bp.efi_memmap = orig_bp->efi_memmap;
bp.efi_memmap_size = orig_bp->efi_memmap_size;
bp.efi_memdesc_size = orig_bp->efi_memdesc_size;
bp.efi_memdesc_version = orig_bp->efi_memdesc_version;
bp.console_info.num_cols = orig_bp->console_info.num_cols;
bp.console_info.num_rows = orig_bp->console_info.num_rows;
bp.console_info.orig_x = orig_bp->console_info.orig_x;
bp.console_info.orig_y = orig_bp->console_info.orig_y;
bp.fpswa = orig_bp->fpswa;
/* If a ramdisk was supplied and I didn't original have one,
* use it.
*/
if (orig_bp->initrd_size && (!bp.initrd_size)) {
bp.initrd_start = orig_bp->initrd_start;
bp.initrd_size = orig_bp->initrd_size;
}
/* If a command line was supplied append it */
if (orig_bp->command_line) {
append_command_line((char *)(orig_bp->command_line));
}
}
static void convert_bhdr_params(Elf_Bhdr *bhdr)
{
unsigned char *note, *end;
char *ldr_name, *ldr_version, *firmware;
ldr_name = ldr_version = firmware = 0;
note = ((char *)bhdr) + sizeof(*bhdr);
end = ((char *)bhdr) + bhdr->b_size;
while(note < end) {
Elf_Nhdr *hdr;
unsigned char *n_name, *n_desc, *next;
hdr = (Elf_Nhdr *)note;
n_name = note + sizeof(*hdr);
n_desc = n_name + ((hdr->n_namesz + 3) & ~3);
next = n_desc + ((hdr->n_descsz + 3) & ~3);
if (next > end)
break;
#if 0
printf("n_type: %x n_name(%d): n_desc(%d): \n",
hdr->n_type, hdr->n_namesz, hdr->n_descsz);
#endif
if (hdr->n_namesz == 0) {
switch(hdr->n_type) {
case EBN_FIRMWARE_TYPE:
firmware = n_desc;
break;
case EBN_BOOTLOADER_NAME:
ldr_name = n_desc;
break;
case EBN_BOOTLOADER_VERSION:
ldr_version = n_desc;
break;
case EBN_COMMAND_LINE:
append_command_line(n_desc);
break;
}
}
else if ((hdr->n_namesz == 10) &&
(memcmp(n_name, "Etherboot", 10) == 0)) {
switch(hdr->n_type) {
case EB_IA64_SYSTAB:
{
uint64_t *systabp = (void *)n_desc;
bp.efi_systab = *systabp;
break;
}
case EB_IA64_FPSWA:
{
uint64_t *fpswap = (void *)n_desc;
bp.fpswa = *fpswap;
break;
}
case EB_IA64_CONINFO:
memcpy(&bp.console_info, n_desc, sizeof(bp.console_info));
break;
case EB_IA64_MEMMAP:
{
struct efi_mem_map {
uint64_t map_size;
uint64_t map_key;
uint64_t descriptor_size;
uint64_t descriptor_version;
uint8_t map[40];
} *map = (void *)n_desc;
bp.efi_memmap = (uint64_t)&map->map;
bp.efi_memmap_size = map->map_size;
bp.efi_memdesc_size = map->descriptor_size;
bp.efi_memdesc_version = map->descriptor_version;
break;
}
}
}
note = next;
}
if (ldr_name && ldr_version) {
printf("Loader: %s version: %s\n",
ldr_name, ldr_version);
}
if (firmware) {
printf("Firmware: %s\n",
firmware);
}
}
void *convert_params(unsigned long arg1, unsigned long r28,
struct image_parameters *params)
{
struct ia64_boot_param *orig_bp;
Elf_Bhdr *bhdr = (Elf_Bhdr*)arg1;
/* handle the options I can easily deal with */
bp.command_line = (unsigned long)&params->cmdline;
bp.initrd_start = params->initrd_start;
bp.initrd_size = params->initrd_size;
orig_bp = (struct ia64_boot_param *)r28;
if (bhdr->b_signature == 0x0E1FB007) {
convert_bhdr_params(bhdr);
}
else {
convert_ia64_boot_params(orig_bp);
}
return &bp;
}