| #include <stdbool.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <console.h> |
| #include <dprintf.h> |
| #include <syslinux/loadfile.h> |
| #include <syslinux/linux.h> |
| #include <syslinux/pxe.h> |
| #include "core.h" |
| |
| const char *globaldefault = NULL; |
| const char *append = NULL; |
| |
| /* Will be called from readconfig.c */ |
| int new_linux_kernel(char *okernel, char *ocmdline) |
| { |
| const char *kernel_name = NULL, *args = NULL; |
| struct initramfs *initramfs = NULL; |
| char *temp; |
| void *kernel_data; |
| size_t kernel_len, cmdline_len; |
| bool opt_quiet = false; |
| char *initrd_name, *cmdline; |
| |
| dprintf("okernel = %s, ocmdline = %s", okernel, ocmdline); |
| |
| if (okernel) |
| kernel_name = okernel; |
| else if (globaldefault) |
| kernel_name = globaldefault; |
| |
| if (ocmdline) |
| args = ocmdline; |
| else if (append) |
| args = append; |
| |
| cmdline_len = strlen("BOOT_IMAGE=") + strlen(kernel_name); |
| cmdline_len += 1; /* space between BOOT_IMAGE and args */ |
| cmdline_len += strlen(args); |
| cmdline_len += 1; /* NUL-termination */ |
| |
| cmdline = malloc(cmdline_len); |
| if (!cmdline) { |
| printf("Failed to alloc memory for cmdline\n"); |
| return 1; |
| } |
| |
| sprintf(cmdline, "BOOT_IMAGE=%s %s", kernel_name, args); |
| |
| /* "keeppxe" handling */ |
| #if IS_PXELINUX |
| extern char KeepPXE; |
| |
| if (strstr(cmdline, "keeppxe")) |
| KeepPXE |= 1; |
| #endif |
| |
| if (strstr(cmdline, "quiet")) |
| opt_quiet = true; |
| |
| if (!opt_quiet) |
| printf("Loading %s... ", kernel_name); |
| |
| if (loadfile(kernel_name, &kernel_data, &kernel_len)) { |
| if (opt_quiet) |
| printf("Loading %s ", kernel_name); |
| printf("failed: "); |
| goto bail; |
| } |
| |
| if (!opt_quiet) |
| printf("ok\n"); |
| |
| /* Find and load initramfs */ |
| temp = strstr(cmdline, "initrd="); |
| if (temp) { |
| /* Initialize the initramfs chain */ |
| initramfs = initramfs_init(); |
| if (!initramfs) |
| goto bail; |
| |
| temp += 6; /* strlen("initrd") */ |
| do { |
| size_t n = 0; |
| char *p; |
| |
| temp++; /* Skip = or , */ |
| |
| p = temp; |
| while (*p != ' ' && *p != ',' && *p) { |
| p++; |
| n++; |
| } |
| |
| initrd_name = malloc(n + 1); |
| if (!initrd_name) { |
| printf("Failed to allocate space for initrd\n"); |
| goto bail; |
| } |
| |
| snprintf(initrd_name, n + 1, "%s", temp); |
| temp += n; |
| |
| if (!opt_quiet) |
| printf("Loading %s...", initrd_name); |
| |
| if (initramfs_load_archive(initramfs, initrd_name)) { |
| if (opt_quiet) |
| printf("Loading %s ", initrd_name); |
| free(initrd_name); |
| printf("failed: "); |
| goto bail; |
| } |
| |
| free(initrd_name); |
| |
| if (!opt_quiet) |
| printf("ok\n"); |
| } while (*temp == ','); |
| } |
| |
| /* This should not return... */ |
| syslinux_boot_linux(kernel_data, kernel_len, initramfs, NULL, cmdline); |
| printf("Booting kernel failed: "); |
| |
| bail: |
| free(cmdline); |
| printf("%s\n", strerror(errno)); |
| return 1; |
| } |