|
|
1.1 ! root 1: /* ! 2: * ! 3: * <bootinfo_load.c> ! 4: * ! 5: * bootinfo file loader ! 6: * ! 7: * Copyright (C) 2009 Laurent Vivier ([email protected]) ! 8: * ! 9: * Original XML parser by Blue Swirl <[email protected]> ! 10: * ! 11: * This program is free software; you can redistribute it and/or ! 12: * modify it under the terms of the GNU General Public License ! 13: * version 2 ! 14: * ! 15: */ ! 16: ! 17: #include "config.h" ! 18: #include "libopenbios/bindings.h" ! 19: #include "libopenbios/bootinfo_load.h" ! 20: #include "libopenbios/ofmem.h" ! 21: #include "libc/vsprintf.h" ! 22: ! 23: //#define DEBUG_BOOTINFO ! 24: ! 25: #ifdef DEBUG_BOOTINFO ! 26: #define DPRINTF(fmt, args...) \ ! 27: do { printk("%s: " fmt, __func__ , ##args); } while (0) ! 28: #else ! 29: #define DPRINTF(fmt, args...) \ ! 30: do { } while (0) ! 31: #endif ! 32: ! 33: static char * ! 34: get_device( const char *path ) ! 35: { ! 36: int i; ! 37: static char buf[1024]; ! 38: ! 39: for (i = 0; i < sizeof(buf) && path[i] && path[i] != ':'; i++) ! 40: buf[i] = path[i]; ! 41: buf[i] = 0; ! 42: ! 43: return buf; ! 44: } ! 45: ! 46: static char * ! 47: get_partition( const char *path ) ! 48: { ! 49: static char buf[2]; ! 50: ! 51: buf[0] = '\0'; ! 52: buf[1] = '\0'; ! 53: ! 54: while ( *path && *path != ':' ) ! 55: path++; ! 56: ! 57: if (!*path) ! 58: return buf; ! 59: path++; ! 60: ! 61: if (path[0] == ',' || !strchr(path, ',')) /* if there is not a ',' or no partition id then return */ ! 62: return buf; ! 63: ! 64: /* Must be a partition id */ ! 65: buf[0] = path[0]; ! 66: ! 67: return buf; ! 68: } ! 69: ! 70: static char * ! 71: get_filename( const char * path , char **dirname) ! 72: { ! 73: static char buf[1024]; ! 74: char *filename; ! 75: ! 76: while ( *path && *path != ':' ) ! 77: path++; ! 78: ! 79: if (!*path) { ! 80: *dirname = NULL; ! 81: return NULL; ! 82: } ! 83: path++; ! 84: ! 85: while ( *path && isdigit(*path) ) ! 86: path++; ! 87: ! 88: if (*path == ',') ! 89: path++; ! 90: ! 91: strncpy(buf, path, sizeof(buf)); ! 92: buf[sizeof(buf) - 1] = 0; ! 93: ! 94: filename = strrchr(buf, '\\'); ! 95: if (filename) { ! 96: *dirname = buf; ! 97: (*filename++) = 0; ! 98: } else { ! 99: *dirname = NULL; ! 100: filename = buf; ! 101: } ! 102: ! 103: return filename; ! 104: } ! 105: ! 106: int ! 107: is_bootinfo(char *bootinfo) ! 108: { ! 109: return (strncasecmp(bootinfo, "<chrp-boot", 10) ? 0 : -1); ! 110: } ! 111: ! 112: int ! 113: bootinfo_load(struct sys_info *info, const char *filename) ! 114: { ! 115: // Currently not implemented ! 116: return LOADER_NOT_SUPPORT; ! 117: } ! 118: ! 119: /* ! 120: Parse SGML structure like: ! 121: <chrp-boot> ! 122: <description>Debian/GNU Linux Installation on IBM CHRP hardware</description> ! 123: <os-name>Debian/GNU Linux for PowerPC</os-name> ! 124: <boot-script>boot &device;:\install\yaboot</boot-script> ! 125: <icon size=64,64 color-space=3,3,2> ! 126: ! 127: CHRP system bindings are described at: ! 128: http://playground.sun.com/1275/bindings/chrp/chrp1_7a.ps ! 129: */ ! 130: ! 131: void ! 132: bootinfo_init_program(void) ! 133: { ! 134: char *base; ! 135: int proplen; ! 136: phandle_t chosen; ! 137: int tag, taglen, script, scriptlen, scriptvalid, entity, chrp; ! 138: char tagbuf[128], c; ! 139: char *device, *filename, *directory, *partition; ! 140: int current, size; ! 141: char *bootscript; ! 142: char *tmp; ! 143: char bootpath[1024]; ! 144: ! 145: /* Parse the boot script */ ! 146: ! 147: chosen = find_dev("/chosen"); ! 148: tmp = get_property(chosen, "bootpath", &proplen); ! 149: memcpy(bootpath, tmp, proplen); ! 150: bootpath[proplen] = 0; ! 151: ! 152: DPRINTF("bootpath %s\n", bootpath); ! 153: ! 154: device = get_device(bootpath); ! 155: partition = get_partition(bootpath); ! 156: filename = get_filename(bootpath, &directory); ! 157: ! 158: feval("load-base"); ! 159: base = (char*)cell2pointer(POP()); ! 160: ! 161: feval("load-size"); ! 162: size = POP(); ! 163: ! 164: bootscript = malloc(size); ! 165: if (bootscript == NULL) { ! 166: DPRINTF("Can't malloc %d bytes\n", size); ! 167: return; ! 168: } ! 169: ! 170: if (!is_bootinfo(base)) { ! 171: DPRINTF("Not a valid bootinfo memory image\n"); ! 172: free(bootscript); ! 173: return; ! 174: } ! 175: ! 176: chrp = 0; ! 177: tag = 0; ! 178: taglen = 0; ! 179: script = 0; ! 180: scriptvalid = 0; ! 181: scriptlen = 0; ! 182: entity = 0; ! 183: current = 0; ! 184: while (current < size) { ! 185: ! 186: c = base[current++]; ! 187: ! 188: if (c == '<') { ! 189: script = 0; ! 190: tag = 1; ! 191: taglen = 0; ! 192: } else if (c == '>') { ! 193: tag = 0; ! 194: tagbuf[taglen] = '\0'; ! 195: if (strncasecmp(tagbuf, "chrp-boot", 9) == 0) { ! 196: chrp = 1; ! 197: } else if (chrp == 1) { ! 198: if (strncasecmp(tagbuf, "boot-script", 11) == 0) { ! 199: script = 1; ! 200: scriptlen = 0; ! 201: } else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) { ! 202: ! 203: script = 0; ! 204: bootscript[scriptlen] = '\0'; ! 205: ! 206: DPRINTF("got bootscript %s\n", ! 207: bootscript); ! 208: ! 209: scriptvalid = -1; ! 210: ! 211: break; ! 212: } else if (strncasecmp(tagbuf, "/chrp-boot", 10) == 0) ! 213: break; ! 214: } ! 215: } else if (tag && taglen < sizeof(tagbuf)) { ! 216: tagbuf[taglen++] = c; ! 217: } else if (script && c == '&') { ! 218: entity = 1; ! 219: taglen = 0; ! 220: } else if (entity && c ==';') { ! 221: entity = 0; ! 222: tagbuf[taglen] = '\0'; ! 223: if (strncasecmp(tagbuf, "lt", 2) == 0) { ! 224: bootscript[scriptlen++] = '<'; ! 225: } else if (strncasecmp(tagbuf, "gt", 2) == 0) { ! 226: bootscript[scriptlen++] = '>'; ! 227: } else if (strncasecmp(tagbuf, "device", 6) == 0) { ! 228: strcpy(bootscript + scriptlen, device); ! 229: scriptlen += strlen(device); ! 230: } else if (strncasecmp(tagbuf, "partition", 9) == 0) { ! 231: strcpy(bootscript + scriptlen, partition); ! 232: scriptlen += strlen(partition); ! 233: } else if (strncasecmp(tagbuf, "directory", 9) == 0) { ! 234: strcpy(bootscript + scriptlen, directory); ! 235: scriptlen += strlen(directory); ! 236: } else if (strncasecmp(tagbuf, "filename", 8) == 0) { ! 237: strcpy(bootscript + scriptlen, filename); ! 238: scriptlen += strlen(filename); ! 239: } else if (strncasecmp(tagbuf, "full-path", 9) == 0) { ! 240: strcpy(bootscript + scriptlen, bootpath); ! 241: scriptlen += strlen(bootpath); ! 242: } else { /* unknown, keep it */ ! 243: bootscript[scriptlen] = '&'; ! 244: strcpy(bootscript + scriptlen + 1, tagbuf); ! 245: scriptlen += taglen + 1; ! 246: bootscript[scriptlen] = ';'; ! 247: scriptlen++; ! 248: } ! 249: } else if (entity && taglen < sizeof(tagbuf)) { ! 250: tagbuf[taglen++] = c; ! 251: } else if (script && scriptlen < size) { ! 252: bootscript[scriptlen++] = c; ! 253: } ! 254: } ! 255: ! 256: /* If the payload is bootinfo then we execute it immediately */ ! 257: if (scriptvalid) { ! 258: DPRINTF("bootscript: %s\n", bootscript); ! 259: feval(bootscript); ! 260: } ! 261: else ! 262: DPRINTF("Unable to parse bootinfo bootscript\n"); ! 263: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.