summaryrefslogtreecommitdiff
path: root/packages/kexecboot/files/kexecboot-rewrite.patch
diff options
context:
space:
mode:
authorant <ant@unknown.openembedded.org>2008-09-04 10:16:43 +0000
committerThomas Kunze <thommycheck@gmx.de>2008-09-04 10:16:43 +0000
commit309c832c2c21ceb97fd589ebce8327d0d2bba731 (patch)
treee4e59eca6ec4cf7e3bbca8f0620a9b8bc86e830b /packages/kexecboot/files/kexecboot-rewrite.patch
parent23ccc2156ae978b7183877bd884396a22f5c168c (diff)
kexecboot: add patch to read mtdparts from /proc/cmdline
initramfs-kexecboot: add rotation parameter for c7x0 linux-kexecboot_2.6.26: change defconfigs
Diffstat (limited to 'packages/kexecboot/files/kexecboot-rewrite.patch')
-rw-r--r--packages/kexecboot/files/kexecboot-rewrite.patch344
1 files changed, 344 insertions, 0 deletions
diff --git a/packages/kexecboot/files/kexecboot-rewrite.patch b/packages/kexecboot/files/kexecboot-rewrite.patch
new file mode 100644
index 0000000000..4f252061ab
--- /dev/null
+++ b/packages/kexecboot/files/kexecboot-rewrite.patch
@@ -0,0 +1,344 @@
+--- kexecboot-0.3.orig/kexecboot.h 2008-09-03 02:35:40.000000000 +0400
++++ kexecboot-0.3/kexecboot.h 2008-09-03 02:36:04.000000000 +0400
+@@ -24,6 +24,10 @@
+ #include <string.h>
+ #include <linux/input.h>
+ #include <termios.h>
++#include <unistd.h>
++#include <signal.h>
++#include <sys/wait.h>
++#include <ctype.h>
+ #include "fb.h"
+ #include "devicescan.h"
+ #include "res/logo-img.h"
+@@ -33,4 +37,14 @@
+ #include "res/memory-img.h"
+ #include "res/radeon-font.h"
+
++/* Macro for dealing with NULL strings */
++#define strlenn(s) ( (NULL != s) ? (strlen(s)) : 0 )
++
++/* Tags we want from /proc/cmdline */
++char *wanted_tags[] = {
++ "mtdparts",
++ NULL
++};
++
++
+ #endif
+--- kexecboot-0.3.orig/kexecboot.c 2008-09-03 02:35:40.000000000 +0400
++++ kexecboot-0.3/kexecboot.c 2008-09-03 03:33:05.000000000 +0400
+@@ -78,20 +78,293 @@
+ fb_render(fb);
+ }
+
++/*
++ * Function: get_extra_cmdline()
++ * It gets wanted tags from original cmdline.
++ * Takes 2 args:
++ * - extra_cmdline - buffer to store cmdline parameters;
++ * - extra_cmdline_size - size of buffer
++ * (inc. terminating '\0').
++ * Return values:
++ * - length of extra_cmdline on success (w/o term. zero);
++ * - -1 on error;
++ * - (- length of extra_cmdline - 1) on insufficient buffer space.
++ */
++
++int get_extra_cmdline(char *const extra_cmdline, const size_t extra_cmdline_size)
++{
++ char *p, *t, *tag = NULL;
++ char line[COMMAND_LINE_SIZE];
++ int i, len, sp_size;
++ int sum_len = 0;
++ int wanted_tag_found = 0;
++ int overflow = 0;
++
++ const char proc_cmdline_path[] = "/proc/cmdline";
++
++ /* Open /proc/cmdline and read cmdline */
++ FILE *f = fopen(proc_cmdline_path, "r");
++ if (NULL == f) {
++ perror("Can't open /proc/cmdline");
++ return -1;
++ }
++
++ if ( NULL == fgets(line, sizeof(line), f) ) {
++ perror("Can't read /proc/cmdline");
++ fclose(f);
++ return -1;
++ }
++
++ fclose(f);
++
++ /* clean up buffer before parsing */
++ t = extra_cmdline;
++ *t = '\0';
++
++ p = line-1; /* because of ++p below */
++
++ sp_size = 0; /* size of (first) space */
++
++ do {
++ ++p;
++
++ if ( (NULL == tag) && (isalnum(*p)) ) {
++ /* new tag found */
++ tag = p;
++ } else if (tag) {
++ /* we are working on some tag */
++
++ if (isspace(*p) || ('\0' == *p) || ('=' == *p) ) {
++ /* end of tag or '=' found */
++
++ if (!wanted_tag_found) {
++ /* search in wanted_tags */
++ for (i = 0; wanted_tags[i] != NULL; i++) {
++ if ( 0 == strncmp(wanted_tags[i], tag, p-tag) ) {
++ /* match found */
++ wanted_tag_found = 1;
++ break;
++ }
++ }
++ }
++
++ if ( ('=' != *p) && wanted_tag_found ) {
++ /* end of wanted tag found -> copy */
++
++ len = p - tag;
++ if ( (sum_len + len + sp_size) < extra_cmdline_size ) {
++ if (sp_size) {
++ /* prepend space when have tags already */
++ *t = ' ';
++ ++t;
++ *t = '\0';
++ ++sum_len;
++ } else {
++ sp_size = sizeof(char);
++ }
++
++ /* NOTE: tag is not null-terminated so copy only
++ * len chars and terminate it directly
++ */
++ strncpy(t, tag, len);
++ /* move pointer to position after copied tag */
++ t += len ;
++ /* null-terminate */
++ *t = '\0';
++ /* update summary length */
++ sum_len += len;
++ } else {
++ /* we have no space - skip this tag */
++ overflow = 1;
++ }
++
++ /* reset wanted_tag_found */
++ wanted_tag_found = 0;
++ }
++
++ /* reset tag */
++ if (!wanted_tag_found) tag = NULL;
++
++ }
++ }
++
++ } while ('\0' != *p);
++
++ if (overflow) return -sum_len-1;
++ return sum_len;
++}
++
++/*
++ * Function: kexec_execw()
++ * (execve and wait)
++ * kexecboot's replace of system() call without /bin/sh invocation.
++ * During execution of the command, SIGCHLD will be blocked,
++ * and SIGINT and SIGQUIT will be ignored (like system() does).
++ * Takes 2 args (execve()-like):
++ * - path - full path to executable file
++ * - argv[] - array of args for executed file (command options e.g.)
++ * - envp[] - array of environment strings ("key=value")
++ * Return value:
++ * - command exit status on success
++ * - -1 on error (e.g. fork() failed)
++ */
++int kexec_execw(const char *path, char *const argv[], char *const envp[])
++{
++ pid_t pid;
++ struct sigaction ignore, old_int, old_quit;
++ sigset_t masked, oldmask;
++ int status;
++
++ /* Block SIGCHLD and ignore SIGINT and SIGQUIT */
++ /* Do this before the fork() to avoid races */
++
++ ignore.sa_handler = SIG_IGN;
++ sigemptyset(&ignore.sa_mask);
++ ignore.sa_flags = 0;
++ sigaction(SIGINT, &ignore, &old_int);
++ sigaction(SIGQUIT, &ignore, &old_quit);
++
++ sigemptyset(&masked);
++ sigaddset(&masked, SIGCHLD);
++ sigprocmask(SIG_BLOCK, &masked, &oldmask);
++
++ pid = fork();
++
++ if (pid < 0)
++ /* can't fork */
++ return -1;
++ else if (pid == 0) {
++ /* it is child */
++ sigaction(SIGINT, &old_int, NULL);
++ sigaction(SIGQUIT, &old_quit, NULL);
++ sigprocmask(SIG_SETMASK, &oldmask, NULL);
++
++ /* replace child with executed file */
++ execve(path, (char *const *)argv, (char *const *)envp);
++ /* should not happens but... */
++ _exit(127);
++ }
++
++ /* it is parent */
++
++ /* wait for our child and store status */
++ waitpid(pid, &status, 0);
++
++ /* restore signal handlers */
++ sigaction(SIGINT, &old_int, NULL);
++ sigaction(SIGQUIT, &old_quit, NULL);
++ sigprocmask(SIG_SETMASK, &oldmask, NULL);
++
++ return status;
++}
++
+ void start_kernel(struct boot *boot)
+ {
+- //kexec --command-line="CMDLINE" -l /mnt/boot/zImage
+- char command[COMMAND_LINE_SIZE + 60];
+- mount(boot->device, "/mnt", boot->fstype, MS_RDONLY, NULL);
+- if( boot->cmdline )
+- sprintf(command,"/usr/sbin/kexec --command-line=\"%s root=%s rootfstype=%s\" -l %s",
+- boot->cmdline, boot->device, boot->fstype, boot->kernelpath);
+- else
+- sprintf(command,"kexec -l %s", boot->kernelpath);
+- system(command);
+-// puts(command);
+- umount("/mnt");
+- system("/usr/sbin/kexec -e");
++ /* we use var[] instead of *var because sizeof(var) using */
++ const char mount_point[] = "/mnt";
++ const char kexec_path[] = "/usr/sbin/kexec";
++
++ const char str_cmdline_start[] = "--command-line=";
++ const char str_root[] = " root=";
++ const char str_rootfstype[] = " rootfstype=";
++ const char str_rootwait[] = " rootwait";
++
++ /* empty environment */
++ char *const envp[] = { NULL };
++
++ const char *kexec_load_argv[] = { NULL, "-l", NULL, NULL, NULL };
++ const char *kexec_exec_argv[] = { NULL, "-e", NULL};
++
++ char extra_cmdline_buffer[COMMAND_LINE_SIZE];
++ char *extra_cmdline, *cmdline_arg = NULL;
++ int n, idx;
++
++ kexec_exec_argv[0] = kexec_path;
++ kexec_load_argv[0] = kexec_path;
++
++ /* --command-line arg generation */
++ idx = 2; /* kexec_load_argv current option index */
++
++ /* get some parts of cmdline from boot loader (e.g. mtdparts) */
++ n = get_extra_cmdline( extra_cmdline_buffer,
++ sizeof(extra_cmdline_buffer) );
++ if ( -1 == n ) {
++ /* clean up extra_cmdline on error */
++ extra_cmdline = NULL;
++/* } else if ( n < -1 ) { */
++ /* Do something when we have no space to get all wanted tags */
++ /* Now do nothing ;) */
++ } else {
++ extra_cmdline = extra_cmdline_buffer;
++ }
++
++ /* fill '--command-line' option */
++ if (boot->cmdline || extra_cmdline || boot->device) {
++ /* allocate space */
++ n = strlenn(str_cmdline_start) + strlenn(boot->cmdline) +
++ sizeof(char) + strlenn(extra_cmdline) +
++ strlenn(str_root) + strlenn(boot->device) +
++ strlenn(str_rootfstype) + strlenn(boot->fstype) +
++ strlenn(str_rootwait) + sizeof(char);
++
++ cmdline_arg = (char *)malloc(n);
++ if (NULL == cmdline_arg) {
++ perror("Can't allocate memory for cmdline_arg");
++ /* Should we exit?
++ exit(-1);
++ */
++ } else {
++ strcat(cmdline_arg, str_cmdline_start);
++ if (extra_cmdline)
++ strcat(cmdline_arg, extra_cmdline);
++ if (boot->cmdline && extra_cmdline)
++ strcat(cmdline_arg, " ");
++ if (boot->cmdline)
++ strcat(cmdline_arg, boot->cmdline);
++ if (boot->device) {
++ strcat(cmdline_arg, str_root);
++ strcat(cmdline_arg, boot->device);
++ if (boot->fstype) {
++ strcat(cmdline_arg, str_rootfstype);
++ strcat(cmdline_arg, boot->fstype);
++ }
++ }
++ strcat(cmdline_arg, str_rootwait);
++
++ kexec_load_argv[idx] = cmdline_arg;
++ ++idx;
++ }
++ }
++
++ /* Append kernelpath as last arg of kexec */
++ kexec_load_argv[idx] = boot->kernelpath;
++
++ /* Debug
++ fprintf(stderr, "%s\n%s\n%s\n%s\n", kexec_load_argv[0],
++ kexec_load_argv[1], kexec_load_argv[2],
++ kexec_load_argv[3]); */
++
++ /* Mount boot device */
++ if ( -1 == mount(boot->device, mount_point, boot->fstype,
++ MS_RDONLY, NULL) ) {
++ perror("Can't mount boot device");
++ exit(-1);
++ }
++
++ /* Load kernel */
++ n = kexec_execw(kexec_path, (char *const *)kexec_load_argv, envp);
++ if (-1 == n) {
++ perror("Kexec can't load kernel");
++ exit(-1);
++ }
++
++ if (cmdline_arg)
++ free(cmdline_arg);
++
++ umount(mount_point);
++
++ /* Boot new kernel */
++ execve(kexec_path, (char *const *)kexec_exec_argv, envp);
+ }
+
+ int main(int argc, char **argv)
+@@ -219,5 +492,6 @@
+ tcsetattr(fileno(stdin), TCSANOW, &old);
+ fb_destroy(fb);
+ start_kernel(bl->list[choice]);
+- return 0;
++ /* When we reach this point then some error was occured */
++ return -1;
+ }