diff options
author | ant <ant@unknown.openembedded.org> | 2008-09-04 10:16:43 +0000 |
---|---|---|
committer | Thomas Kunze <thommycheck@gmx.de> | 2008-09-04 10:16:43 +0000 |
commit | 309c832c2c21ceb97fd589ebce8327d0d2bba731 (patch) | |
tree | e4e59eca6ec4cf7e3bbca8f0620a9b8bc86e830b /packages/kexecboot/files/kexecboot-rewrite.patch | |
parent | 23ccc2156ae978b7183877bd884396a22f5c168c (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.patch | 344 |
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; + } |