/* * Add extra tags if UBI device is found. * * Sample commandline required to boot ubifs: * root=ubi0_0 ubi.mtd=2 rootfstype=ubifs */ static int check_for_ubi(struct boot_item_t *item, char *cmdline_arg, char *mount_dev, char *mount_fstype, const char *str_ubirootdev, const char *str_ubimtd, char *str_mtd_id, const char *str_ubimtd_off) { int u; if (!strncmp(item->fstype,"ubi",3)) { /* mtd id [0-15] - one or two digits */ if(isdigit(atoi(item->device+strlen(item->device)-2))) { strcpy(str_mtd_id, item->device+strlen(item->device)-2); strcat(str_mtd_id, item->device+strlen(item->device)-1); } else { strcpy(str_mtd_id, item->device+strlen(item->device)-1); } /* get corresponding ubi dev to mount */ u = find_attached_ubi_device(str_mtd_id); sprintf(mount_dev, "/dev/ubi%d", u); /* FIXME: first volume is hardcoded */ strcat(mount_dev, "_0"); /* HARDCODED: we assume it's ubifs */ strcpy(mount_fstype,"ubifs"); /* extra cmdline tags when we detect ubi */ strcat(cmdline_arg, str_ubirootdev); /* FIXME: first volume is hardcoded */ strcat(cmdline_arg, "_0"); strcat(cmdline_arg, str_ubimtd); strcat(cmdline_arg, str_mtd_id); #ifdef UBI_VID_HDR_OFFSET strcat(cmdline_arg, str_ubimtd_off); #endif return 1; } else { return 0; } }
void start_kernel(struct params_t *params, int choice) { /* we use var[] instead of *var because sizeof(var) using */ #ifdef USE_HOST_DEBUG const char kexec_path[] = "/bin/echo"; #else const char kexec_path[] = KEXEC_PATH; #endif const char mount_point[] = MOUNTPOINT; const char str_cmdline_start[] = "--command-line=root="; const char str_rootfstype[] = " rootfstype="; const char str_rootwait[] = " rootwait"; const char str_ubirootdev[] = "ubi0"; const char str_ubimtd[] = " ubi.mtd="; /* max ' ubi.mtd=15' len 11 +1 = 12 */ #ifdef UBI_VID_HDR_OFFSET const char str_ubimtd_off[] = UBI_VID_HDR_OFFSET; #else const char str_ubimtd_off[] = ""; #endif char mount_dev[16]; char mount_fstype[16]; char str_mtd_id[3]; /* Tags passed from host kernel cmdline to kexec'ed kernel */ const char str_mtdparts[] = " mtdparts="; const char str_fbcon[] = " fbcon="; const char str_initrd_start[] = "--initrd="; /* empty environment */ char *const envp[] = { NULL }; const char *load_argv[] = { NULL, "-l", NULL, NULL, NULL, NULL }; const char *exec_argv[] = { NULL, "-e", NULL, NULL}; char *cmdline_arg = NULL, *initrd_arg = NULL; int n, idx, u; struct stat sinfo; struct boot_item_t *item; item = params->bootcfg->list[choice]; exec_argv[0] = kexec_path; load_argv[0] = kexec_path; /* --command-line arg generation */ idx = 2; /* load_argv current option index */ /* fill '--command-line' option */ if (item->device) { /* default device to mount */ strcpy(mount_dev, item->device); /* allocate space */ n = sizeof(str_cmdline_start) + strlen(item->device) + sizeof(str_ubirootdev) + 2 + sizeof(str_ubimtd) + 2 + sizeof(str_ubimtd_off) + 1 + sizeof(str_rootwait) + sizeof(str_rootfstype) + strlen(item->fstype) + 2 + sizeof(str_mtdparts) + strlenn(params->cfg->mtdparts) + sizeof(str_fbcon) + strlenn(params->cfg->fbcon) + sizeof(char) + strlenn(item->cmdline); cmdline_arg = (char *)malloc(n); if (NULL == cmdline_arg) { perror("Can't allocate memory for cmdline_arg"); } else { strcpy(cmdline_arg, str_cmdline_start); /* --command-line=root= */ if (item->fstype) { /* default fstype to mount */ strcpy(mount_fstype, item->fstype); /* extra tags when we detect UBI */ if (!strncmp(item->fstype,"ubi",3)) { /* mtd id [0-15] - one or two digits */ if(isdigit(atoi(item->device+strlen(item->device)-2))) { strcpy(str_mtd_id, item->device+strlen(item->device)-2); strcat(str_mtd_id, item->device+strlen(item->device)-1); } else { strcpy(str_mtd_id, item->device+strlen(item->device)-1); } /* get corresponding ubi dev to mount */ u = find_attached_ubi_device(str_mtd_id); sprintf(mount_dev, "/dev/ubi%d", u); /* FIXME: first volume is hardcoded */ strcat(mount_dev, "_0"); /* HARDCODED: we assume it's ubifs */ strcpy(mount_fstype,"ubifs"); /* extra cmdline tags when we detect ubi */ strcat(cmdline_arg, str_ubirootdev); /* FIXME: first volume is hardcoded */ strcat(cmdline_arg, "_0"); strcat(cmdline_arg, str_ubimtd); strcat(cmdline_arg, str_mtd_id); #ifdef UBI_VID_HDR_OFFSET strcat(cmdline_arg, ","); strcat(cmdline_arg, str_ubimtd_off); #endif } else { strcat(cmdline_arg, item->device); /* root=item->device */ } strcat(cmdline_arg, str_rootfstype); strcat(cmdline_arg, mount_fstype); } strcat(cmdline_arg, str_rootwait); if (params->cfg->mtdparts) { strcat(cmdline_arg, str_mtdparts); strcat(cmdline_arg, params->cfg->mtdparts); } if (params->cfg->fbcon) { strcat(cmdline_arg, str_fbcon); strcat(cmdline_arg, params->cfg->fbcon); } if (item->cmdline) { strcat(cmdline_arg, " "); strcat(cmdline_arg, item->cmdline); } load_argv[idx] = cmdline_arg; ++idx; } } /* fill '--initrd' option */ if (item->initrd) { /* allocate space */ n = sizeof(str_initrd_start) + strlen(item->initrd); initrd_arg = (char *)malloc(n); if (NULL == initrd_arg) { perror("Can't allocate memory for initrd_arg"); } else { strcpy(initrd_arg, str_initrd_start); /* --initrd= */ strcat(initrd_arg, item->initrd); load_argv[idx] = initrd_arg; ++idx; } } /* Append kernelpath as last arg of kexec */ load_argv[idx] = item->kernelpath; DPRINTF("load_argv: %s, %s, %s, %s, %s", load_argv[0], load_argv[1], load_argv[2], load_argv[3], load_argv[4]); /* Mount boot device */ if ( -1 == mount(mount_dev, mount_point, mount_fstype, MS_RDONLY, NULL) ) { perror("Can't mount boot device"); exit(-1); } /* Load kernel */ n = fexecw(kexec_path, (char *const *)load_argv, envp); if (-1 == n) { perror("Kexec can't load kernel"); exit(-1); } umount(mount_point); dispose(cmdline_arg); dispose(initrd_arg); /* Check /proc/sys/net presence */ if ( -1 == stat("/proc/sys/net", &sinfo) ) { if (ENOENT == errno) { /* We have no network, don't issue ifdown() while kexec'ing */ exec_argv[2] = "-x"; DPRINTF("No network is detected, disabling ifdown()"); } else { perror("Can't stat /proc/sys/net"); } } DPRINTF("exec_argv: %s, %s, %s", exec_argv[0], exec_argv[1], exec_argv[2]); /* Boot new kernel */ execve(kexec_path, (char *const *)exec_argv, envp); }