Index: Makefile =================================================================== RCS file: /cvsroot/free60/xell/Makefile,v retrieving revision 1.7 diff -u -p -r1.7 Makefile --- Makefile 22 Jan 2008 23:20:41 -0000 1.7 +++ Makefile 2 Feb 2008 20:24:39 -0000 @@ -32,9 +32,9 @@ LWIP_OBJS = ./lwip/core/tcp_in.o \ OBJS = startup2.o main.o string.o vsprintf.o ctype.o time.o \ cache.o $(LWIP_OBJS) network.o tftp.o httpd/httpd.o httpd/vfs.o dtc.o \ - cdrom.o xenos.o font_8x16.o + cdrom.o xenos.o font_8x16.o smc.o menu.o -BUILD = xell-serial xell-readcd +BUILD = xell-serial xell-readcd TARGETS = $(foreach name,$(BUILD),$(addprefix $(name).,bin elf elf32)) Index: cdrom.c =================================================================== RCS file: /cvsroot/free60/xell/cdrom.c,v retrieving revision 1.1 diff -u -p -r1.1 cdrom.c --- cdrom.c 19 Mar 2007 20:10:03 -0000 1.1 +++ cdrom.c 2 Feb 2008 20:24:40 -0000 @@ -292,26 +292,25 @@ int read_directory(int sector, int len, extern int execute_elf_at(void *dst, int len, const char *args); -void try_boot_cdrom(void) +int iso9660_load_file(char *filename, void* addr) { - int sector, size, kernel_sector, kernel_size; + int sector, size, file_sector, file_size; + char fnamebuf[258]; struct pvd_s *pvd = 0; - set_modeb(); - printf(" * reading CD/DVD...\n"); if (read_sector(sector_buffer, 16, 1)) { printf(" ! failed to read PVD\n"); - return; + return -1; } pvd = (void*)sector_buffer; if (memcmp(sector_buffer, "\1CD001\1", 8)) { printf(" ! no iso9660!\n"); - return; + return -1; } printf("root_direntry offset: %d\n", (int)(&((struct pvd_s *)0)->root_direntry)); @@ -321,46 +320,62 @@ void try_boot_cdrom(void) if (!sector) { printf(" ! root direntry not found\n"); - return; + return -1; } printf(" ! root at lba=%02x, size=%d\n", sector, size); - if ( - read_directory(sector, size, "vmlinux;1", &kernel_sector, &kernel_size) && - read_directory(sector, size, "vmlinux.;1", &kernel_sector, &kernel_size)) + + strcpy(fnamebuf, filename); + strcat(fnamebuf, ";1"); + if (read_directory(sector, size, fnamebuf, &file_sector, &file_size)) { - printf(" ! xenon kernel image not found\n"); - return; + strcpy(fnamebuf, filename); + strcat(fnamebuf, ".;1"); + if (read_directory(sector, size, fnamebuf, &file_sector, &file_size)) + { + printf(" ! '%s' not found\n", filename); + return -1; + } } - printf(" ! found kernel at lba=%d, size=%d\n", kernel_sector, kernel_size); + printf(" ! found '%s' at lba=%d, size=%d\n", fnamebuf, file_sector, file_size); - printf(" ! loading kernel...\n"); + printf(" ! loading file...\n"); - void *addr = (void*)LOADER_RAW; - - int s = kernel_size; + int s = file_size; while (1) { - printf("\r * %08x -> %p... ", kernel_sector, addr); + printf("\r * %08x -> %p... ", file_sector, addr); - int num = (kernel_size + 0x7ff) / 0x800; + int num = (s + 0x7ff) / 0x800; if (num > 64) num = 64; - if (read_sector(addr, kernel_sector, num)) + if (read_sector(addr, file_sector, num)) { printf("\n ! read sector failed!\n"); break; } - addr += num * 0x800; kernel_sector+=num; kernel_size -= num * 0x800; - if (kernel_size <= 0) + addr += num * 0x800; file_sector+=num; s -= num * 0x800; + if (s <= 0) { - printf("\n * done! executing kernel!\n"); - execute_elf_at((void*)LOADER_RAW, s, ""); - return; + printf("\n * done!\n"); + return file_size; } } + return -1; +} + +void try_boot_cdrom(char *filename) +{ + int size; + set_modeb(); + + if (!filename) + filename = "vmlinux"; + if ((size = iso9660_load_file(filename, (void*)LOADER_RAW)) >= 0) { + execute_elf_at((void*)LOADER_RAW, size, ""); + } } Index: main.c =================================================================== RCS file: /cvsroot/free60/xell/main.c,v retrieving revision 1.5 diff -u -p -r1.5 main.c --- main.c 24 Jan 2008 22:04:43 -0000 1.5 +++ main.c 2 Feb 2008 20:24:41 -0000 @@ -7,9 +7,15 @@ #include #include "version.h" -extern void try_boot_cdrom(void); +#define MENU +/* cdrom.c: */ +extern int iso9660_load_file(char *filename, void* addr); +extern void try_boot_cdrom(char *); +/* xenos.c: */ extern void xenos_init(); extern void xenos_putch(const char c); +/* menu.c: */ +extern void main_menu(); #include "elf_abi.h" @@ -19,7 +25,7 @@ static void putch(unsigned char c) *(volatile uint32_t*)0x80000200ea001014 = (c << 24) & 0xFF000000; } -static int kbhit(void) +int kbhit(void) { uint32_t status; @@ -172,7 +178,9 @@ int start(int pir, unsigned long hrmor, { secondary_hold_addr = 0; +#ifndef TARGET_xell int exc[]={0x100, 0x200, 0x300, 0x380, 0x400, 0x480, 0x500, 0x600, 0x700, 0x800, 0x900, 0x980, 0xC00, 0xD00, 0xF00, 0xF20, 0x1300, 0x1600, 0x1700, 0x1800}; +#endif int i; @@ -182,6 +190,9 @@ int start(int pir, unsigned long hrmor, printf("\nXeLL - Xenon linux loader " LONGVERSION "\n"); +#ifdef TARGET_xell + printf(" * WARNING: Bootstrapped XeLL not catching CPUs...\n"); +#else printf(" * Attempting to catch all CPUs...\n"); for (i=0; i>24)&0xff), (int)((ip.addr>>16)&0xff), (int)((ip.addr>>8)&0xff), (int)(ip.addr&0xff) + printf(" * XeLL network config: %d.%d.%d.%d / %d.%d.%d.%d\n", + NTOA(ipaddr), NTOA(netmask)); +} + void network_poll() { mftb(&now); Index: string.c =================================================================== RCS file: /cvsroot/free60/xell/string.c,v retrieving revision 1.1 diff -u -p -r1.1 string.c --- string.c 19 Mar 2007 20:10:04 -0000 1.1 +++ string.c 2 Feb 2008 20:24:41 -0000 @@ -53,7 +53,6 @@ int strnicmp(const char *s1, const char } #endif -char * ___strtok; #endif #ifndef __HAVE_ARCH_STRCPY @@ -249,8 +248,9 @@ size_t strnlen(const char * s, size_t co } #endif -#if 0 +#if 1 #ifndef __HAVE_ARCH_STRSPN +char * ___strtok; /** * strspn - Calculate the length of the initial substring of @s which only * contain letters in @accept Index: vsprintf.c =================================================================== RCS file: /cvsroot/free60/xell/vsprintf.c,v retrieving revision 1.1 diff -u -p -r1.1 vsprintf.c --- vsprintf.c 19 Mar 2007 20:10:05 -0000 1.1 +++ vsprintf.c 2 Feb 2008 20:24:42 -0000 @@ -51,7 +51,7 @@ long simple_strtol(const char *cp,char * /* we use this so that we can do without the ctype library */ #define is_digit(c) ((c) >= '0' && (c) <= '9') -static int skip_atoi(const char **s) +int skip_atoi(const char **s) { int i=0; Index: xenos.c =================================================================== RCS file: /cvsroot/free60/xell/xenos.c,v retrieving revision 1.4 diff -u -p -r1.4 xenos.c --- xenos.c 24 Jan 2008 22:04:43 -0000 1.4 +++ xenos.c 2 Feb 2008 20:24:42 -0000 @@ -33,7 +33,7 @@ uint32_t xenos_color[2] = { 0xD8444E00, /* can't initialize xenos_fb with zero due to late BSS init, * instead init it in xenos_preinit() */ -unsigned char *xenos_fb; +unsigned char *xenos_fb = 0LL; int cursor_x, cursor_y, max_x, max_y; @@ -121,7 +121,11 @@ void xenos_newline() { } static inline void xenos_putch_impl(const char c) { - if (c == '\r') { + if (c == '\t') { + /* move to the next multiple of 8 */ + cursor_x += 7; + cursor_x &= ~7; + } else if (c == '\r') { cursor_x = 0; } else if (c == '\n') { xenos_newline(); @@ -159,18 +163,18 @@ void xenos_putch(const char c) { /* This was added to improve userfriendlyness */ char* xenos_ascii = "\n" - " ======================================================\n" - " = ========================== ==== ==\n" - " = =============================== ===== == == =\n" - " = =============================== ========= ==== =\n" - " = ======== = ==== ==== === ==== ==== =\n" - " = ==== = == = == = == === === ==== =\n" - " = ======== ======= == == ===== == ==== =\n" - " = ======== ======= ===== ===== ===== == ==== =\n" - " = ======== ======= = == = === === == == =\n" - " = ======== ======== ==== ===== ===== ==\n" - " ======================================================\n" - "\n XeLL - Xenon Linux Loader " VERSION "\n\n"; + " ######################################################\n" + " # ########################## #### ##\n" + " # ############################### ##### ## ## #\n" + " # ############################### ######### #### #\n" + " # ######## # #### #### ### #### #### #\n" + " # #### # ## # ## # ## ### ### #### #\n" + " # ######## ####### ## ## ##### ## #### #\n" + " # ######## ####### ##### ##### ##### ## #### #\n" + " # ######## ####### # ## # ### ### ## ## #\n" + " # ######## ######## #### ##### ##### ##\n" + " ######################################################\n" + " XeLL - Xenon Linux Loader " VERSION "\n\n"; void xenos_asciiart() { char *p = xenos_ascii; Index: httpd/fsdata.c =================================================================== RCS file: /cvsroot/free60/xell/httpd/fsdata.c,v retrieving revision 1.1 diff -u -p -r1.1 fsdata.c --- httpd/fsdata.c 19 Mar 2007 20:10:07 -0000 1.1 +++ httpd/fsdata.c 2 Feb 2008 20:24:42 -0000 @@ -1,3 +1,4 @@ static struct vfs_entry_s vfs_entries[]={ + {"/index.dhtml", "

hello World!

", 21, "text/html"}, {0, 0, 0, 0} }; Index: include/network.h =================================================================== RCS file: /cvsroot/free60/xell/include/network.h,v retrieving revision 1.1 diff -u -p -r1.1 network.h --- include/network.h 19 Mar 2007 20:10:12 -0000 1.1 +++ include/network.h 2 Feb 2008 20:24:42 -0000 @@ -3,5 +3,6 @@ void network_init(); void network_poll(); +void print_network_config(); #endif --- /dev/null 2008-02-01 11:16:58.813598151 +0100 +++ menu.c 2008-02-02 21:24:02.899577932 +0100 @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include +#include +#include + +extern int kbhit(void); +extern int getchar(void); +extern int iso9660_load_file(char *filename, void* addr); +extern void try_boot_cdrom(char *); + +/* from smc.c: */ +extern int smc_poll(); +extern int smc_getkey(); +extern int ignore_power; + +/* from network.c: */ +extern struct ip_addr ipaddr, netmask, gw; +extern struct netif netif; + + +/*----------------------------------------------------------------------*/ + +#define MAXOPTS 32 + +enum source { + SRC_DEFAULT, + SRC_TFTP, + SRC_CD, + SRC_HDD, + SRC_MAX +}; + +char *sourcenames[SRC_MAX] = { + "same source as XeLL", + "TFTP", + "CD-ROM", + "Hard Disk" +}; + +struct file { +}; + +struct boot { + enum source src; + char *path; + char *title; +}; + +void print_bootopt(struct boot *b) { + printf("Boot config \"%s\"\n", b->title); + printf(" Kernel: \"%s\" %i\n", b->path, b->src); +} + +#define isspace(c) ((c)==' ' || (c)=='\r' || (c)=='\n' || (c)=='\t') + +/* skip leading whitespace in string at ptr */ +#define SKIP_WS(ptr) while (isspace(*ptr)) ptr++; + +/* macro to parse a command and execute according code + * + * @ptr: pointer to command line start (will be changed) + * @opt: command name (i.e. "timeout") + * @optlen: strlen(opt) (i.e. 7) + * @code: what to execute when the command is matched + **/ +#define IFOPT(ptr, opt, optlen, code) \ + if ((0 == strncmp(ptr, opt, optlen)) && isspace(ptr[optlen])) { \ + ptr += optlen + 1; \ + SKIP_WS(ptr); \ + code; \ + } + +/* global boot config vars: + * boot_optc: number of boot entries + * boot_opt: boot menu entries + * boot_opt[0] = default fallback entries, no real boot menu + **/ +int boot_optc; +struct boot boot_opt[MAXOPTS]; + +int boot_timeout; +struct in_addr boot_ip, boot_netmask, boot_server; +char *tftp_server; + +void parse_source(enum source src, char *data) { + if (boot_optc == MAXOPTS) { + printf("Maximum number of menu entries reached!\n"); + return; + } + char *tmp = strpbrk(data, " \t"); + if (tmp) { + *tmp++ = '\0'; + SKIP_WS(tmp); + boot_opt[boot_optc].src = src; + boot_opt[boot_optc].path = data; + boot_opt[boot_optc].title = tmp; + boot_optc++; + } else { + printf("Missing whitespace in source line: \"%s\"\n", data); + } +} + +void parse_input_line(char *data) { + char *tmp; + + SKIP_WS(data); + IFOPT(data, "ip", 2, + tmp = strchr(data, '/'); + if (tmp) { + *tmp = '\0'; + tmp++; + inet_aton(data, (struct in_addr*)&ipaddr.addr); + inet_aton(tmp, (struct in_addr*)&netmask.addr); + netif_set_addr(&netif, &ipaddr, &netmask, &gw); + print_network_config(); + } else printf("Error: missing netmask"); + ) else + IFOPT(data, "server", 6, + inet_aton(data, &boot_server); + tftp_server = data; + //printf("TFTP: %08x\n", boot_server.s_addr); + ) else + IFOPT(data, "timeout", 7, + boot_timeout = skip_atoi(&data); + ) else + IFOPT(data, "tftp", 4, + parse_source(SRC_TFTP, data); + ) else + IFOPT(data, "cd", 2, + parse_source(SRC_CD, data); + ) else + IFOPT(data, "hdd", 3, + parse_source(SRC_HDD, data); + ) else { + printf("Ignoring unknown command: \"%s\"\n", data); + } +} + +/* parse a zero terminated config file string */ +void parse_config(char *data) { + char *next, *eol; + + boot_optc = 0; + boot_timeout = 30; + + while (data && *data) { + + /* find EOL and replace with NUL byte */ + eol = strpbrk(data, "\r\n"); + if (eol == NULL) { + next = NULL; + } else { + *eol = '\0'; + next = eol + 1; + } + //printf("%p param %s\n", data, data); + + parse_input_line(data); + data = next; + + if (data) + SKIP_WS(data); + } +} + +#define POWER_BTN -3 + +int user_prompt(int defaultchoice, int max, int timeout) { + int redraw = 1; + int min = 1; + int delta, olddelta = -1; + int ignore_power_last = ignore_power; + tb_t start, now; + + mftb(&start); + delta = 0; + while (delta <= timeout) { + /* measure seconds since menu start */ + mftb(&now); + delta = tb_diff_sec(&now, &start); + /* test if prompt update is needed */ + if (delta != olddelta) { + olddelta = delta; + redraw = 1; + } + /* redraw prompt - clear line, then print prompt */ + if (redraw) { + printf(" \r[%02d] > ", + timeout - delta); + redraw = 0; + } + + if (smc_poll()) { + int ch = smc_getkey(); + if (ch >= min && ch <= max) + return ch; + redraw = 1; + /* check for Power button */ + if (ignore_power_last != ignore_power) + return POWER_BTN; + } + + if (kbhit()) { + char ch = getchar(); + int num = ch - '0'; + printf("\nyou pressed '%c'\n", ch); + if (num >= min && num <= max) + return num; + redraw = 1; + } + + network_poll(); + } + printf("Timeout.\n"); + return defaultchoice; +} + +char xell_config[4096]; + +void main_menu() { + int defchoice = 1; + int cfg_size = iso9660_load_file("xell.cfg", xell_config); + if (cfg_size >= 0) { + printf("XeLL config:\n%s", xell_config); + } + + parse_config(xell_config); + + /* Allow power button for menu selection */ + ignore_power = boot_optc; + + while (1) { + int opt; + printf("XeLL Main Menu. Please choose from:\n\n"); + for (opt = 1; opt <= boot_optc; opt++) { + printf(" <%i> %s - %s%s\n", opt, boot_opt[opt-1].title, + sourcenames[boot_opt[opt-1].src], + defchoice == opt?" (default)":""); + } + int choice = user_prompt(defchoice, boot_optc, boot_timeout); + if (choice == POWER_BTN) { + defchoice++; + boot_timeout = 5; + continue; + } + + struct boot *b = &boot_opt[choice-1]; + printf("[###] > Booting %s: %s from %s\n", b->title, b->path, sourcenames[b->src]); + switch (b->src) { + case SRC_TFTP: + boot_tftp(tftp_server, b->path); + break; + case SRC_CD: + try_boot_cdrom(b->path); + break; + default: + printf("Not yet implemented, aborting menu!\n"); + //usleep(1000); + return; + } + } +} + --- /dev/null 2008-02-01 11:16:58.813598151 +0100 +++ smc.c 2008-02-02 21:06:14.972974096 +0100 @@ -0,0 +1,88 @@ +/* smc-ir.c - minimal IR receiver driver for XeLL + * + * Copyright (C) 2008 Georg Lukas + * + * This software is provided under the GNU GPL License v2. + */ +#include +#include +#include +#include + +volatile uint32_t *smc_base = (volatile uint32_t*)0x200ea001000LL; + +int ignore_power = 3; + +static inline unsigned int swap32(unsigned int v) +{ + return ((v&0xFF) << 24) | ((v&0xFF00)<<8) | ((v&0xFF0000)>>8) | ((v&0xFF000000)>>24); +} + + +int smc_hasdata() { + return (swap32(smc_base[0x94/4]) & 4); +} + +int smc_get(uint32_t *msg) { + int pos; + if (swap32(smc_base[0x94/4]) & 4) { + smc_base[0x94/4] = swap32(4); + for (pos=0; pos < 4; pos++) + msg[pos] = smc_base[0x90/4]; + smc_base[0x94/4] = 0; + return 1; + } + return 0; +} + +void smc_send(uint32_t *msg) { + int pos; + while (!(swap32(smc_base[0x84/4]) & 4)); + + smc_base[0x84/4] = swap32(4); + for (pos=0; pos < 4; pos++) + smc_base[0x80/4] = msg[pos]; + smc_base[0x84/4] = 0; +} + +int smc_lastkey = -1; + +int smc_getkey() { + int ret = smc_lastkey; + smc_lastkey = -1; + return ret; +} + +int smc_poll() { + unsigned char msg[16], ans[16]; + memset(msg, 0, 16); + + if (smc_get((void*)&msg)) { + if (ignore_power && + ((msg[0] == 0x83 && msg[1] == 0x11 && msg[2] == 0x01) +#ifdef BLOCK_IR_REMOTE_POWER + || (msg[0] == 0x83 && msg[1] == 0x20 && msg[2] == 0x01) +#endif + )) { + printf("PowerNAK"); + memset(ans, 0, 16); + ans[0] = 0x82; + ans[1] = 0x04; + ans[2] = 0x33; + smc_send((void*)ans); + ignore_power--; + } else + printf("Received"); + int i; + if (msg[0] == 0x83 && msg[1] == 0x23) { + smc_lastkey = msg[3]; + printf(" IR code %d\n", smc_lastkey); + } else + for (i=0; i<16; i++) + printf(" %02x", (uint32_t)msg[i]); + printf("\n"); + return 1; + } + return 0; +} + --- /dev/null 2008-02-01 11:16:58.813598151 +0100 +++ xell.cfg 2008-02-02 21:02:52.986856142 +0100 @@ -0,0 +1,9 @@ +ip 192.168.0.250/255.255.255.0 +server 192.168.0.31 +timeout 99 + +cd vmlinux Linux-sda2 +cd vmlinux-initramfs Recovery Linux +hdd vmlinux to be implemented +tftp /tftpboot/xenon Xenon from TFTP +tftp /tftpboot/vmlinux-2.6.21.sda2.sata.fbfix Linux-sda2 from TFTP