kexec-map-file.patch (5339B)
1 From 35b8bad0343a4afd9ad914e377e64bd02667c563 Mon Sep 17 00:00:00 2001 2 From: Daniel Barlow <dan@telent.net> 3 Date: Sun, 19 Mar 2023 17:30:30 +0000 4 Subject: [PATCH] add --map-file option to map arbitrary files into physmem 5 6 This is useful e.g. in conjunction with the MTD PHRAM device on 7 embedded devices: a kernel can be booted with kexec and a root 8 filesystem entirely in RAM to see if it works before writing it 9 to flash. 10 --- 11 kexec/kexec.8 | 14 ++++++++++++- 12 kexec/kexec.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 13 kexec/kexec.h | 4 +++- 14 3 files changed, 73 insertions(+), 2 deletions(-) 15 16 diff --git a/kexec/kexec.8 b/kexec/kexec.8 17 index 3a344c5..3140ccb 100644 18 --- a/kexec/kexec.8 19 +++ b/kexec/kexec.8 20 @@ -143,10 +143,17 @@ into the current kernel. 21 .B \-p\ (\-\-load\-panic) 22 Load the new kernel for use on panic. 23 .TP 24 -.BI \-t\ (\-\-type= type ) 25 +.BI \-m\ (\-\-type= type ) 26 Specify that the new kernel is of this 27 .I type. 28 .TP 29 +.BI \-t\ (\-\-map-file= filename@addr ) 30 +Read 31 +.I filename 32 +and arrange for it to be mapped into physical memory at the address 33 +.I addr. 34 +This option may be repeated if there are multiple files to map. 35 +.TP 36 .BI \-s\ (\-\-kexec-file-syscall) 37 Specify that the new KEXEC_FILE_LOAD syscall should be used exclusively. 38 .TP 39 @@ -206,6 +213,11 @@ Reuse initrd from first boot. 40 .BI \-\-print-ckr-size 41 Print crash kernel region size, if available. 42 43 +.PP 44 +Options taking an 45 +.I addr 46 +parameter will accept a memory address written in hexadecimal (with leading 47 +0x), or octal (leading 0), or decimal (no leading sigil). 48 49 .SH SUPPORTED KERNEL FILE TYPES AND OPTIONS 50 .B Beoboot-x86 51 diff --git a/kexec/kexec.c b/kexec/kexec.c 52 index 36bb2ad..c3b40a4 100644 53 --- a/kexec/kexec.c 54 +++ b/kexec/kexec.c 55 @@ -63,6 +63,13 @@ static unsigned long kexec_flags = 0; 56 static unsigned long kexec_file_flags = 0; 57 int kexec_debug = 0; 58 59 +#define MAPPED_FILES_MAX 10 /* arbitrary number */ 60 +struct mapped_file { 61 + const char *filename; 62 + unsigned long long phys_address; 63 +} mapped_files[MAPPED_FILES_MAX] = { { .filename = NULL } }; 64 + 65 + 66 void dbgprint_mem_range(const char *prefix, struct memory_range *mr, int nr_mr) 67 { 68 int i; 69 @@ -771,6 +778,19 @@ static int my_load(const char *type, int fileind, int argc, char **argv, 70 } 71 info.kexec_flags |= native_arch; 72 73 + for(struct mapped_file *m = mapped_files; m->filename; m++) { 74 + off_t file_size = 0; 75 + char *buf = slurp_file(m->filename, &file_size); 76 + add_buffer(&info, 77 + buf, file_size, file_size, sizeof (void *), 78 + m->phys_address, 79 + mem_max, 1); 80 + free(m->filename); 81 + /* do we free() memory returned by slurp_file()? 82 + * we don't know if it was mmaped, so maybe not 83 + */ 84 + }; 85 + 86 result = file_type[i].load(argc, argv, kernel_buf, kernel_size, &info); 87 if (result < 0) { 88 switch (result) { 89 @@ -1035,6 +1055,8 @@ void usage(void) 90 " load code into.\n" 91 " --mem-max=<addr> Specify the highest memory address to\n" 92 " load code into.\n" 93 + " --map-file=<filename@addr> Map a file into memory for the\n" 94 + " new kernel before kexec.\n" 95 " --reuseinitrd Reuse initrd from first boot.\n" 96 " --print-ckr-size Print crash kernel region size.\n" 97 " --load-preserve-context Load the new kernel and preserve\n" 98 @@ -1396,6 +1418,33 @@ static void print_crashkernel_region_size(void) 99 printf("%" PRIu64 "\n", (start != end) ? (end - start + 1) : 0UL); 100 } 101 102 +static int add_mapped_file(char * optarg) 103 +{ 104 + char *at = strchr(optarg, '@'); 105 + if(!at) 106 + return 1; 107 + 108 + struct mapped_file *m = mapped_files; 109 + struct mapped_file *m_end = mapped_files + 110 + ((sizeof mapped_files) / (sizeof mapped_files[0])); 111 + 112 + while(m->filename && m < m_end) 113 + m++; 114 + 115 + if(m >= m_end) 116 + return 1; 117 + 118 + m->phys_address = strtoull(at + 1, NULL, 0); 119 + if(m->phys_address == 0) 120 + return 1; 121 + 122 + m->filename = strndup(optarg, at - optarg); 123 + 124 + (m+1)->filename = NULL; 125 + return 0; 126 +} 127 + 128 + 129 int main(int argc, char *argv[]) 130 { 131 int has_opt_load = 0; 132 @@ -1521,6 +1570,14 @@ int main(int argc, char *argv[]) 133 kexec_file_flags |= KEXEC_FILE_ON_CRASH; 134 kexec_flags = KEXEC_ON_CRASH; 135 break; 136 + case OPT_MAP_FILE: 137 + if(add_mapped_file(optarg)) { 138 + fprintf(stderr, 139 + "Bad option value or too many mapped files in --mapped-file=%s\n", 140 + optarg); 141 + return 1; 142 + } 143 + break; 144 case OPT_MEM_MIN: 145 mem_min = strtoul(optarg, &endptr, 0); 146 if (*endptr) { 147 diff --git a/kexec/kexec.h b/kexec/kexec.h 148 index 0d820ad..78022b6 100644 149 --- a/kexec/kexec.h 150 +++ b/kexec/kexec.h 151 @@ -224,6 +224,7 @@ extern int file_types; 152 #define OPT_STATUS 'S' 153 #define OPT_MEM_MIN 256 154 #define OPT_MEM_MAX 257 155 +#define OPT_MAP_FILE 'm' 156 #define OPT_REUSE_INITRD 258 157 #define OPT_LOAD_PRESERVE_CONTEXT 259 158 #define OPT_LOAD_JUMP_BACK_HELPER 260 159 @@ -258,8 +259,9 @@ extern int file_types; 160 { "debug", 0, 0, OPT_DEBUG }, \ 161 { "status", 0, 0, OPT_STATUS }, \ 162 { "print-ckr-size", 0, 0, OPT_PRINT_CKR_SIZE }, \ 163 + { "map-file", 1, 0, OPT_MAP_FILE }, \ 164 165 -#define KEXEC_OPT_STR "h?vdfixyluet:pscaS" 166 +#define KEXEC_OPT_STR "h?vdfixyluet:pscaSm" 167 168 extern void dbgprint_mem_range(const char *prefix, struct memory_range *mr, int nr_mr); 169 extern void die(const char *fmt, ...) 170 -- 171 2.38.1 172