kexec-tools-static_1.101.bb : fix compile on newer kernels based on work done
[vuplus_openembedded] / recipes / kexec / files / kexec-arm-atags.patch
1 ---
2  kexec/arch/arm/kexec-zImage-arm.c |  259 ++++++++++++++++++++++++++++++++++++--
3  1 file changed, 252 insertions(+), 7 deletions(-)
4
5 Index: kexec-tools-1.101/kexec/arch/arm/kexec-zImage-arm.c
6 ===================================================================
7 --- kexec-tools-1.101.orig/kexec/arch/arm/kexec-zImage-arm.c
8 +++ kexec-tools-1.101/kexec/arch/arm/kexec-zImage-arm.c
9 @@ -1,11 +1,82 @@
10 +/*
11 + * - 08/21/2007 ATAG support added by Uli Luckas <u.luckas@road.de>
12 + *
13 + */
14  #define _GNU_SOURCE
15  #include <stdio.h>
16  #include <string.h>
17  #include <stdlib.h>
18  #include <errno.h>
19  #include <limits.h>
20 +#include <stdint.h>
21 +#include <getopt.h>
22 +#include <arch/options.h>
23  #include "../../kexec.h"
24  
25 +#define COMMAND_LINE_SIZE 1024
26 +#define BOOT_PARAMS_SIZE 1536
27 +
28 +struct tag_header {
29 +       uint32_t size;
30 +       uint32_t tag;
31 +};
32 +
33 +/* The list must start with an ATAG_CORE node */
34 +#define ATAG_CORE       0x54410001
35 +
36 +struct tag_core {
37 +       uint32_t flags;     /* bit 0 = read-only */
38 +       uint32_t pagesize;
39 +       uint32_t rootdev;
40 +};
41 +
42 +/* it is allowed to have multiple ATAG_MEM nodes */
43 +#define ATAG_MEM       0x54410002
44 +
45 +struct tag_mem32 {
46 +       uint32_t   size;
47 +       uint32_t   start;  /* physical start address */
48 +};
49 +
50 +/* describes where the compressed ramdisk image lives (virtual address) */
51 +/*
52 + * this one accidentally used virtual addresses - as such,
53 + * it's deprecated.
54 + */
55 +#define ATAG_INITRD     0x54410005
56 +
57 +/* describes where the compressed ramdisk image lives (physical address) */
58 +#define ATAG_INITRD2    0x54420005
59 +
60 +struct tag_initrd {
61 +        uint32_t start;    /* physical start address */
62 +        uint32_t size;     /* size of compressed ramdisk image in bytes */
63 +};
64 +
65 +/* command line: \0 terminated string */
66 +#define ATAG_CMDLINE    0x54410009
67 +
68 +struct tag_cmdline {
69 +       char    cmdline[1];     /* this is the minimum size */
70 +};
71 +
72 +/* The list ends with an ATAG_NONE node. */
73 +#define ATAG_NONE       0x00000000
74 +
75 +struct tag {
76 +       struct tag_header hdr;
77 +       union {
78 +               struct tag_core  core;
79 +               struct tag_mem32        mem;
80 +               struct tag_initrd       initrd;
81 +               struct tag_cmdline      cmdline;
82 +       } u;
83 +};
84 +
85 +#define tag_next(t)     ((struct tag *)((uint32_t *)(t) + (t)->hdr.size))
86 +#define byte_size(t)    ((t)->hdr.size << 2)
87 +#define tag_size(type)  ((sizeof(struct tag_header) + sizeof(struct type) + 3) >> 2)
88 +
89  int zImage_arm_probe(const char *buf, off_t len)
90  {
91         /* 
92 @@ -14,21 +85,194 @@ int zImage_arm_probe(const char *buf, of
93          */     
94         return 0;
95  }
96 +
97  void zImage_arm_usage(void)
98  {
99 +       printf( "     --command-line=STRING Set the kernel command line to STRING.\n"
100 +               "     --append=STRING       Set the kernel command line to STRING.\n"
101 +               "     --initrd=FILE         Use FILE as the kernel's initial ramdisk.\n"
102 +               "     --ramdisk=FILE        Use FILE as the kernel's initial ramdisk.\n"
103 +               );
104 +}
105 +
106 +static
107 +struct tag * atag_read_tags(void)
108 +{
109 +       static unsigned long buf[BOOT_PARAMS_SIZE];
110 +       const char fn[]= "/proc/atags";
111 +       FILE *fp;
112 +       fp = fopen(fn, "r");
113 +       if (!fp) {
114 +               fprintf(stderr, "Cannot open %s: %s\n", 
115 +                       fn, strerror(errno));
116 +               return NULL;
117 +       }
118 +
119 +       fread(buf, sizeof(buf[1]), BOOT_PARAMS_SIZE, fp);
120 +       if (ferror(fp)) {
121 +               fprintf(stderr, "Cannot read %s: %s\n",
122 +                       fn, strerror(errno));
123 +               fclose(fp);
124 +               return NULL;
125 +       }
126 +
127 +       fclose(fp);
128 +       return (struct tag *) buf;
129 +}
130 +
131 +
132 +static
133 +int atag_arm_load(struct kexec_info *info, unsigned long base,
134 +       const char *command_line, off_t command_line_len,
135 +       const char *initrd, off_t initrd_len)
136 +{
137 +       struct tag *saved_tags = atag_read_tags();
138 +       char *buf;
139 +       off_t len;
140 +       struct tag *params;
141 +       uint32_t *initrd_start;
142 +       
143 +       buf = xmalloc(getpagesize());
144 +       if (!buf) {
145 +               fprintf(stderr, "Compiling ATAGs: out of memory\n");
146 +               return -1;
147 +       }
148 +
149 +       memset(buf, 0xff, getpagesize());
150 +       params = (struct tag *)buf;
151 +
152 +       if (saved_tags) {
153 +               // Copy tags
154 +               saved_tags = (struct tag *) saved_tags;
155 +               while(byte_size(saved_tags)) {
156 +                       switch (saved_tags->hdr.tag) {
157 +                       case ATAG_INITRD:
158 +                       case ATAG_INITRD2:
159 +                       case ATAG_CMDLINE:
160 +                       case ATAG_NONE:
161 +                               // skip these tags
162 +                               break;
163 +                       default:
164 +                               // copy all other tags
165 +                               memcpy(params, saved_tags, byte_size(saved_tags));
166 +                               params = tag_next(params);
167 +                       }
168 +                       saved_tags = tag_next(saved_tags);
169 +               }
170 +       } else {
171 +               params->hdr.size = 2;
172 +               params->hdr.tag = ATAG_CORE;
173 +               params = tag_next(params);
174 +       }
175 +
176 +       if (initrd) {
177 +               params->hdr.size = tag_size(tag_initrd);
178 +               params->hdr.tag = ATAG_INITRD2;
179 +               initrd_start = &params->u.initrd.start;
180 +               params->u.initrd.size = initrd_len;
181 +               params = tag_next(params);
182 +       }
183 +
184 +       if (command_line) {
185 +               params->hdr.size = (sizeof(struct tag_header) + command_line_len + 3) >> 2;
186 +               params->hdr.tag = ATAG_CMDLINE;
187 +               memcpy(params->u.cmdline.cmdline, command_line,
188 +                       command_line_len);
189 +               params->u.cmdline.cmdline[command_line_len - 1] = '\0';
190 +               params = tag_next(params);
191 +       }
192 +
193 +       params->hdr.size = 0;
194 +       params->hdr.tag = ATAG_NONE;
195 +
196 +       len = ((char *)params - buf) + sizeof(struct tag_header);
197 +
198 +       add_segment(info, buf, len, base, len);
199 +
200 +       if (initrd) {
201 +               struct memory_range *range;
202 +               int ranges;
203 +               get_memory_ranges(&range, &ranges);
204 +               *initrd_start = locate_hole(info, initrd_len, getpagesize(), range[0].start + 0x800000, ULONG_MAX, INT_MAX);
205 +               if (*initrd_start == ULONG_MAX)
206 +                       return -1;
207 +               add_segment(info, initrd, initrd_len, *initrd_start, initrd_len);
208 +       }
209 +
210 +       return 0;
211  }
212 -int zImage_arm_load(int argc, char **argv, const char *buf, off_t len, 
213 +
214 +int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
215         struct kexec_info *info)
216  {
217         unsigned long base;
218 -       unsigned int offset = 0x8000; /* 32k offset from memory start */
219 +       unsigned int atag_offset = 0x1000; /* 4k offset from memory start */
220 +       unsigned int offset = 0x8000;      /* 32k offset from memory start */
221 +       const char *command_line;
222 +       off_t command_line_len;
223 +       const char *ramdisk;
224 +       char *ramdisk_buf;
225 +       off_t ramdisk_length;
226 +       int opt;
227 +#define OPT_APPEND     'a'
228 +#define OPT_RAMDISK    'r'
229 +       static const struct option options[] = {
230 +               KEXEC_ARCH_OPTIONS
231 +               { "command-line",       1, 0, OPT_APPEND },
232 +               { "append",             1, 0, OPT_APPEND },
233 +               { "initrd",             1, 0, OPT_RAMDISK },
234 +               { "ramdisk",            1, 0, OPT_RAMDISK },
235 +               { 0,                    0, 0, 0 },
236 +       };
237 +       static const char short_options[] = KEXEC_ARCH_OPT_STR "a:r:";
238 +
239 +       /*
240 +        * Parse the command line arguments
241 +        */
242 +       command_line = 0;
243 +       command_line_len = 0;
244 +       ramdisk = 0;
245 +       ramdisk_buf = 0;
246 +       ramdisk_length = 0;
247 +       while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
248 +               switch(opt) {
249 +               default:
250 +                       /* Ignore core options */
251 +                       if (opt < OPT_ARCH_MAX) {
252 +                               break;
253 +                       }
254 +               case '?':
255 +                       usage();
256 +                       return -1;
257 +               case OPT_APPEND:
258 +                       command_line = optarg;
259 +                       break;
260 +               case OPT_RAMDISK:
261 +                       ramdisk = optarg;
262 +                       break;
263 +               }
264 +       }
265 +       if (command_line) {
266 +               command_line_len = strlen(command_line) + 1;
267 +               if (command_line_len > COMMAND_LINE_SIZE)
268 +                       command_line_len = COMMAND_LINE_SIZE;
269 +       }
270 +       if (ramdisk) {
271 +               ramdisk_buf = slurp_file(ramdisk, &ramdisk_length);
272 +       }
273 +
274         base = locate_hole(info,len+offset,0,0,ULONG_MAX,INT_MAX);
275         if (base == ULONG_MAX)
276 -       {
277                 return -1;
278 -       }
279 -       base += offset;
280 -       add_segment(info,buf,len,base,len);
281 -       info->entry = (void*)base;
282 +
283 +       if (atag_arm_load(info, base + atag_offset,
284 +                        command_line, command_line_len,
285 +                        ramdisk_buf, ramdisk_length)    == -1)
286 +               return -1;
287 +
288 +       add_segment(info, buf, len, base + offset, len);
289 +
290 +       info->entry = (void*)base + offset;
291 +
292         return 0;
293  }