#include #include #include #include #include "arc.h" #include "prom.h" #define MAX_ARG 64 static char *iargv[MAX_ARG]; static int iargc=0; static char *OSLoadPartition=NULL; static char *OSLoadFilename=NULL; static char *OSLoadOptions=NULL; void prom_flush_cache_all(void ) { ArcFlushAllCaches(); } void prom_restart(void ) { ArcRestart(); } void prom_return_interactive(void ) { ArcEnterInteractiveMode(); } void prom_wait(const char *prompt) { int ch; if (prompt != NULL) puts(prompt); do { ch = getchar(); } while ((ch != EOF) && (((char) ch) != ' ')); } void prom_fatal(const CHAR * message, ...) { va_list ap; if (message != NULL) { printf("FATAL ERROR: "); va_start(ap, message); vprintf(message, ap); va_end(ap); } prom_wait("\n\r--- Press to enter ARC interactive mode ---"); ArcEnterInteractiveMode(); } void prom_init_malloc(void) { MEMORYDESCRIPTOR *current = NULL; unsigned long stack = (unsigned long) ¤t; #ifdef DEBUG printf("stack starts at: 0x%lx\n\r", stack); #endif current = ArcGetMemoryDescriptor(current); if(!current ) { prom_fatal("Can't find any valid memory descriptors!\n\r"); } while (current != NULL) { /* * The spec says we should have an adjacent FreeContiguous * memory area that includes our stack. It would be much * easier to just look for that and give it to malloc, but * the Indy only shows FreeMemory areas, no FreeContiguous. * Oh well. */ if (current->Type == FreeMemory) { unsigned long start = KSEG0ADDR(current->BasePage * PAGE_SIZE); unsigned long end = start + (current->PageCount * PAGE_SIZE); #if DEBUG printf("Free Memory(%u) segment found at (0x%lx,0x%lx).\n\r", current->Type, start, end); #endif /* Leave some space for our stack */ if ((stack >= start) && (stack < end)) end = (stack - (STACK_PAGES * PAGE_SIZE)) & ~(PAGE_SIZE - 1); /* Don't use memory from reserved region */ if ((start >= KERNELADDR) && (start < (KERNELADDR + MAXLOADSIZE))) start = KERNELADDR + MAXLOADSIZE; if ((end > KERNELADDR) && (end <= (KERNELADDR + MAXLOADSIZE))) end = KERNELADDR; if (end > start) { #ifdef DEBUG printf("Adding %lu bytes at 0x%lx to the list of available memory\n\r", end-start, start); #endif malloc_area_add(start, end - start); } } current = ArcGetMemoryDescriptor(current); } } int prom_open(char *name, int mode, FILE *stream) { /* Translate mode to Arc variant */ int amode=OpenReadOnly; if (mode == O_RDWR) amode=OpenReadWrite; return ArcOpen(name, amode, stream); } int prom_close(FILE stream) { return ArcClose(stream); } int prom_seek(FILE stream, long long position, int whence) { LARGEINTEGER apos; SEEKMODE amode=SeekAbsolute; /* Translate generic positioning to ARC positioning */ if (whence == SEEK_CUR) amode=SeekRelative; /* Translate 64 bit long long to Arc representation */ apos.HighPart=position>>32; apos.LowPart=position&0xffffffff; return ArcSeek(stream, &apos, amode); } int prom_write(FILE stream, char *string, unsigned long len, unsigned long *rlen) { return ArcWrite(stream, string, len, rlen); } int prom_read(FILE stream, char *string, unsigned long len, unsigned long *rlen) { return ArcRead(stream, string, len, rlen); } /* we filter these out of the command line */ static char* env_vars[] = { "ConsoleIn=", "ConsoleOut=", "OSLoader=", "OSLoadPartition=", "OSLoadFilename=", "OSLoadOptions=", }; #define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0]))))) static int isEnvVar(const char* arg) { unsigned int i; for (i = 0; i < NENTS(env_vars); i++) { if(strncmp( env_vars[i], arg, strlen(env_vars[i]) ) == 0) return 1; } return 0; } int prom_parse_args(int argc, char **argv) { unsigned long arg; char *equals; size_t len; /* save some things we need later */ for (arg = 1; arg < argc; arg++) { equals = strchr(argv[arg], '='); if (equals != NULL) { len = equals - argv[arg]; if (strncmp(argv[arg], "OSLoadPartition", len) == 0) OSLoadPartition = equals + 1; if (strncmp(argv[arg], "OSLoadFilename", len) == 0) OSLoadFilename = equals + 1; if (strncmp(argv[arg], "OSLoadOptions", len) == 0) { /* Copy options to local memory to avoid overwrite later */ OSLoadOptions = strdup(equals + 1); if (OSLoadOptions == NULL) prom_fatal("Cannot allocate memory for options string\n\r"); } } } /* * in case the user typed "boot a b c" the argv looks like: * scsi(0)..(8)/arcboot a b c OSLoadPartition=.. SystemPartition=.. * argv: `0 `-1`-2`-3`-4 `-5 * we're interested in a,b,c so scan the command line and check for * each argument if it is an environment variable. We're using a fixed * list instead of ArcGetEnvironmentVariable since e.g. the prom sets * "OSLoadOptions=auto" on reboot but * EnvironmentVariable("OSLoadOptions") == NULL */ for( arg = 1; arg < argc; arg++ ) { if(!isEnvVar(argv[arg])) { iargv[iargc++]=strdup(argv[arg]); } else { if (OSLoadOptions) { prom_add_arg(OSLoadOptions); } return (iargc); } } return 0; } void prom_add_arg(char *arg) { iargv[iargc++]=strdup(arg); } char *prom_get_label(void ) { if (iargc > 1 && iargv[1]) { return iargv[1]; } return "Linux"; } char *prom_get_partition(void ) { return OSLoadPartition; } char *prom_get_options(void ) { return OSLoadOptions; } void prom_get_karg(int *argc, char ***argv) { *argc=iargc; *argv=iargv; }