Patrick Williams | b48b7b4 | 2016-08-17 15:04:38 -0500 | [diff] [blame^] | 1 | From de9a6284df8add6ec03e1d9981d0b6d0595bbc69 Mon Sep 17 00:00:00 2001 |
| 2 | From: Andrea Adami <andrea.adami@gmail.com> |
| 3 | Date: Mon, 10 Nov 2014 23:37:23 +0100 |
| 4 | Subject: [PATCH 4/4] kexecboot.c: workaround for absolute kernel and initrd |
| 5 | symlinks |
| 6 | |
| 7 | Add MOUNTPOINT prefix if the kernel/initrd symlinks start with '/'. |
| 8 | Do nothing if the path is a relative symbolic link or not a symlink. |
| 9 | |
| 10 | Fix following situation: |
| 11 | |
| 12 | root@mizar:/var/tmp# ls -al boot/ |
| 13 | total 2076 |
| 14 | drwxr-xr-x 2 root root 4096 lug 5 01:38 . |
| 15 | drwxrwxrwt 4 root root 4096 lug 5 12:26 .. |
| 16 | -rw-r--r-- 1 root root 831 lug 5 01:24 boot.cfg |
| 17 | -rw-r--r-- 1 root root 1322 lug 5 01:24 icon.xpm |
| 18 | lrwxrwxrwx 1 root root 34 lug 5 12:26 zImage -> |
| 19 | /boot/zImage-3.14.5-yocto-standard |
| 20 | -rw-r--r-- 1 root root 2106832 lug 5 01:20 zImage-3.14.5-yocto-standard |
| 21 | |
| 22 | Cannot open `/mnt/boot/zImage': No such file or directory |
| 23 | Nothing has been loaded! |
| 24 | |
| 25 | Signed-off-by: Andrea Adami <andrea.adami@gmail.com> |
| 26 | --- |
| 27 | kexecboot.c | 53 ++++++++++++++++++++++++++++++++++++++++++++--------- |
| 28 | 1 file changed, 44 insertions(+), 9 deletions(-) |
| 29 | |
| 30 | diff --git a/kexecboot.c b/kexecboot.c |
| 31 | index 7268d6b..8a7a7d2 100644 |
| 32 | --- a/kexecboot.c |
| 33 | +++ b/kexecboot.c |
| 34 | @@ -208,11 +208,16 @@ void start_kernel(struct params_t *params, int choice) |
| 35 | const char *load_argv[] = { NULL, "-l", NULL, NULL, NULL, NULL }; |
| 36 | const char *exec_argv[] = { NULL, "-e", NULL, NULL}; |
| 37 | |
| 38 | - char *cmdline_arg = NULL, *initrd_arg = NULL; |
| 39 | + char *cmdline_arg = NULL, *initrd_arg = NULL, *kernel_arg = NULL; |
| 40 | int n, idx, u; |
| 41 | struct stat sinfo; |
| 42 | struct boot_item_t *item; |
| 43 | |
| 44 | + /* buffer for readlink (could be truncated) */ |
| 45 | + char buf[512]; |
| 46 | + int len; |
| 47 | + |
| 48 | + |
| 49 | item = params->bootcfg->list[choice]; |
| 50 | |
| 51 | exec_argv[0] = kexec_path; |
| 52 | @@ -306,10 +311,17 @@ void start_kernel(struct params_t *params, int choice) |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | + /* Mount boot device */ |
| 57 | + if ( -1 == mount(mount_dev, mount_point, mount_fstype, |
| 58 | + MS_RDONLY, NULL) ) { |
| 59 | + perror("Can't mount boot device"); |
| 60 | + exit(-1); |
| 61 | + } |
| 62 | + |
| 63 | /* fill '--initrd' option */ |
| 64 | if (item->initrd) { |
| 65 | /* allocate space */ |
| 66 | - n = sizeof(str_initrd_start) + strlen(item->initrd); |
| 67 | + n = sizeof(str_initrd_start) + strlen(item->initrd) + 1 + sizeof(mount_point) + sizeof(buf); |
| 68 | |
| 69 | initrd_arg = (char *)malloc(n); |
| 70 | if (NULL == initrd_arg) { |
| 71 | @@ -317,24 +329,46 @@ void start_kernel(struct params_t *params, int choice) |
| 72 | } else { |
| 73 | strcpy(initrd_arg, str_initrd_start); /* --initrd= */ |
| 74 | strcat(initrd_arg, item->initrd); |
| 75 | + |
| 76 | + if ((len = readlink(item->initrd, buf, sizeof(buf)-1)) != -1) { |
| 77 | + buf[len] = '\0'; |
| 78 | + /* Fix absolute symlinks: prepend MOUNTPOINT */ |
| 79 | + if (buf[0] == '/') { |
| 80 | + strcpy(initrd_arg, str_initrd_start); /* --initrd= */ |
| 81 | + strcat(initrd_arg, mount_point); |
| 82 | + strcat(initrd_arg, buf); |
| 83 | + } |
| 84 | + } |
| 85 | load_argv[idx] = initrd_arg; |
| 86 | ++idx; |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | /* Append kernelpath as last arg of kexec */ |
| 91 | - load_argv[idx] = item->kernelpath; |
| 92 | + /* allocate space */ |
| 93 | + n = strlen(item->kernelpath) + 1 + sizeof(mount_point) + sizeof(buf); |
| 94 | + |
| 95 | + kernel_arg = (char *)malloc(n); |
| 96 | + if (NULL == kernel_arg) { |
| 97 | + perror("Can't allocate memory for kernel_arg"); |
| 98 | + } else { |
| 99 | + strcpy(kernel_arg, item->kernelpath); |
| 100 | + |
| 101 | + if ((len = readlink(item->kernelpath, buf, sizeof(buf)-1)) != -1) { |
| 102 | + buf[len] = '\0'; |
| 103 | + /* Fix absolute symlinks: prepend MOUNTPOINT */ |
| 104 | + if (buf[0] == '/') { |
| 105 | + strcpy(kernel_arg, mount_point); |
| 106 | + strcat(kernel_arg, buf); |
| 107 | + } |
| 108 | + } |
| 109 | + load_argv[idx] = kernel_arg; |
| 110 | + } |
| 111 | |
| 112 | DPRINTF("load_argv: %s, %s, %s, %s, %s", load_argv[0], |
| 113 | load_argv[1], load_argv[2], |
| 114 | load_argv[3], load_argv[4]); |
| 115 | |
| 116 | - /* Mount boot device */ |
| 117 | - if ( -1 == mount(mount_dev, mount_point, mount_fstype, |
| 118 | - MS_RDONLY, NULL) ) { |
| 119 | - perror("Can't mount boot device"); |
| 120 | - exit(-1); |
| 121 | - } |
| 122 | |
| 123 | /* Load kernel */ |
| 124 | n = fexecw(kexec_path, (char *const *)load_argv, envp); |
| 125 | @@ -347,6 +381,7 @@ void start_kernel(struct params_t *params, int choice) |
| 126 | |
| 127 | dispose(cmdline_arg); |
| 128 | dispose(initrd_arg); |
| 129 | + dispose(kernel_arg); |
| 130 | |
| 131 | /* Check /proc/sys/net presence */ |
| 132 | if ( -1 == stat("/proc/sys/net", &sinfo) ) { |
| 133 | -- |
| 134 | 1.9.1 |
| 135 | |