/* $Id: mkzimage_cmdline.c 590 2006-02-07 14:38:07Z jplack $ */ /* * a little tool to modify the cmdline inside a zImage * Olaf Hering Copyright (C) 2003, 2004 */ /* 2003-10-02, version 1 2003-11-15, version 2: fix short reads if the string is at the end of the file 2004-08-07, version 3: use mmap */ /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation */ #include #include #include #include #include #include #include #include #define MY_VERSION 3 static int activate; static int clear; static int set; static char *string; static char *filename; static const char cmdline_start[] = "cmd_line_start"; static const char cmdline_end[] = "cmd_line_end"; static void my_version(void) { printf("version: %d\n", MY_VERSION); printf("(C) SuSE Linux AG, Nuernberg, Germany, 2003, 2004\n"); return; } static void my_rtfm(const char *app) { printf("modify the built-in cmdline of a CHRP boot image\n"); printf("%s filename\n", app); printf("work with zImage named 'filename'\n"); printf(" [-h] display this help\n"); printf(" [-v] display version\n"); printf(" [-a 0|1] disable/enable built-in cmdline\n"); printf(" overrides whatever is passed from OpenFirmware\n"); printf(" [-s STRING] store STRING in the boot image\n"); printf(" [-c] clear previous content before update\n"); printf(" no option will show the current settings in 'filename'\n"); return; } int main(int argc, char **argv) { struct stat sb; int fd, found; unsigned char *p, *s, *e, *tmp, *active; if (argc < 2) { my_rtfm(argv[0]); exit(1); } while (1) { int i; i = getopt(argc, argv, "a:hcvs:"); if (i == -1) break; switch (i) { case 'a': if (*optarg == '0') activate = -1; else activate = 1; break; case 'c': clear = 1; break; case 'h': my_rtfm(argv[0]); exit(0); case 's': string = strdup(optarg); if (!string) { fprintf(stderr, "set: no mem\n"); exit(1); } set = 1; if (!activate) activate = 1; break; case 'v': my_version(); exit(0); default: printf("unknown option\n"); my_rtfm(argv[0]); exit(1); } } if (argc <= optind) { fprintf(stderr, "filename required\n"); exit(1); } filename = strdup(argv[optind]); if (!filename) { fprintf(stderr, "no mem\n"); exit(1); } fd = open(filename, (activate || clear || set) ? O_RDWR : O_RDONLY); if (fd == -1) goto error; found = stat(filename, &sb); if (found < 0) goto error; if (!S_ISREG(sb.st_mode)) { fprintf(stderr, "%s is not a file\n", filename); exit(1); } p = mmap(NULL, sb.st_size, ((activate || clear || set) ? PROT_WRITE : 0) | PROT_READ, MAP_SHARED, fd, 0); if (p == MAP_FAILED) goto error; s = p; e = p + sb.st_size - sizeof(cmdline_start) - sizeof(cmdline_end); found = 0; while (s < e) { if (memcmp(++s, cmdline_start, sizeof(cmdline_start) - 1) != 0) continue; found = 1; break; } if (!found) goto no_start; found = 0; active = s - 1; tmp = s = s + sizeof(cmdline_start) - 1; e = p + sb.st_size - sizeof(cmdline_end); while (tmp < e) { if (memcmp(++tmp, cmdline_end, sizeof(cmdline_end)) != 0) continue; found = 1; break; } if (!found) goto no_end; if (activate || clear || set) { if (activate) *active = activate > 0 ? '1' : '0'; if (clear) memset(s, 0x0, tmp - s); if (set) snprintf(s, tmp - s, "%s", string); } else { fprintf(stdout, "cmd_line size:%d\n", tmp - s); fprintf(stdout, "cmd_line: %s\n", s); fprintf(stdout, "active: %c\n", *active); } munmap(p, sb.st_size); close(fd); return 0; error: perror(filename); return 1; no_start: fprintf(stderr, "%s: %s not found.\n", filename, cmdline_start); return 1; no_end: fprintf(stderr, "%s: %s not found.\n", filename, cmdline_end); return 1; }