LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File mkzimage_cmdline.c of Package util-linux (Project Base:System)

/*  $Id: mkzimage_cmdline.c 590 2006-02-07 14:38:07Z jplack $ */
/*
 * a little tool to modify the cmdline inside a zImage
 * Olaf Hering <olh@suse.de>  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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>

#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;
}