diff options
-rw-r--r-- | kexec/arch/mips/crashdump-mips.c | 5 | ||||
-rw-r--r-- | kexec/arch/mips/crashdump-mips.h | 2 | ||||
-rw-r--r-- | kexec/arch/mips/kexec-elf-mips.c | 76 |
3 files changed, 80 insertions, 3 deletions
diff --git a/kexec/arch/mips/crashdump-mips.c b/kexec/arch/mips/crashdump-mips.c index aa09c83..d9f4515 100644 --- a/kexec/arch/mips/crashdump-mips.c +++ b/kexec/arch/mips/crashdump-mips.c @@ -334,7 +334,10 @@ static int patch_elf_info(void) if (strncmp(line, "cpu model", 9) == 0) { /* OCTEON uses a different page_offset. */ if (strstr(line, "Octeon")) - elf_info64.page_offset = 0x8000000000000000ULL; + elf_info64.page_offset = OCTEON_PAGE_OFFSET; + /* LOONGSON uses a different page_offset. */ + else if (strstr(line, "Loongson")) + elf_info64.page_offset = LOONGSON_PAGE_OFFSET; break; } } diff --git a/kexec/arch/mips/crashdump-mips.h b/kexec/arch/mips/crashdump-mips.h index 7edd859..55c9925 100644 --- a/kexec/arch/mips/crashdump-mips.h +++ b/kexec/arch/mips/crashdump-mips.h @@ -13,6 +13,8 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline, #endif #define __pa(x) ((unsigned long)(X) & 0x7fffffff) +#define LOONGSON_PAGE_OFFSET 0xffffffff80000000ULL +#define OCTEON_PAGE_OFFSET 0x8000000000000000ULL #define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1) #define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2) diff --git a/kexec/arch/mips/kexec-elf-mips.c b/kexec/arch/mips/kexec-elf-mips.c index a2d11fc..31f4c47 100644 --- a/kexec/arch/mips/kexec-elf-mips.c +++ b/kexec/arch/mips/kexec-elf-mips.c @@ -40,6 +40,77 @@ static const int probe_debug = 0; #define CMDLINE_PREFIX "kexec " static char cmdline_buf[COMMAND_LINE_SIZE] = CMDLINE_PREFIX; +/* Converts unsigned long to ascii string. */ +static void ultoa(unsigned long i, char *str) +{ + int j = 0, k; + char tmp; + + do { + str[j++] = i % 10 + '0'; + } while ((i /= 10) > 0); + str[j] = '\0'; + + /* Reverse the string. */ + for (j = 0, k = strlen(str) - 1; j < k; j++, k--) { + tmp = str[k]; + str[k] = str[j]; + str[j] = tmp; + } +} + +/* Adds initrd parameters to command line. */ +static int cmdline_add_initrd(char *cmdline, unsigned long addr, char *new_para) +{ + int cmdlen, len; + char str[30], *ptr; + + ptr = str; + strcpy(str, new_para); + ptr += strlen(str); + ultoa(addr, ptr); + len = strlen(str); + cmdlen = strlen(cmdline) + len; + if (cmdlen > (COMMAND_LINE_SIZE - 1)) + die("Command line overflow\n"); + strcat(cmdline, str); + + return 0; +} + +/* add initrd to cmdline to compatible with previous platforms. */ +static int patch_initrd_info(char *cmdline, unsigned long base, + unsigned long size) +{ + const char cpuinfo[] = "/proc/cpuinfo"; + char line[MAX_LINE]; + FILE *fp; + unsigned long page_offset = PAGE_OFFSET; + + fp = fopen(cpuinfo, "r"); + if (!fp) { + fprintf(stderr, "Cannot open %s: %s\n", + cpuinfo, strerror(errno)); + return -1; + } + while (fgets(line, sizeof(line), fp) != 0) { + if (strncmp(line, "cpu model", 9) == 0) { + if (strstr(line, "Loongson")) { + /* LOONGSON64 uses a different page_offset. */ + if (arch_options.core_header_type == + CORE_TYPE_ELF64) + page_offset = LOONGSON_PAGE_OFFSET; + cmdline_add_initrd(cmdline, + page_offset + base, " rd_start="); + cmdline_add_initrd(cmdline, size, " rd_size="); + break; + } + } + } + fclose(fp); + return 0; +} + int elf_mips_probe(const char *buf, off_t len) { struct mem_ehdr ehdr; @@ -171,9 +242,10 @@ int elf_mips_load(int argc, char **argv, const char *buf, off_t len, /* Now that the buffer for initrd is prepared, update the dtb * with an appropriate location */ dtb_set_initrd(&dtb_buf, &dtb_length, initrd_base, initrd_base + initrd_size); - } - + /* Add the initrd parameters to cmdline */ + patch_initrd_info(cmdline_buf, initrd_base, initrd_size); + } /* This is a legacy method for commandline passing used * currently by Octeon CPUs only */ add_buffer(info, cmdline_buf, sizeof(cmdline_buf), |