36
36
#define MAXPATH 1024 /* max path name length */
37
37
#define NAMESPACE 16384 /* max bytes for property names */
38
#define TREEWORDS 65536 /* max 32 bit words for property values */
38
#define INIT_TREE_WORDS 65536 /* Initial num words for prop values */
39
39
#define MEMRESERVE 256 /* max number of reserved memory blocks */
40
#define MAX_MEMORY_RANGES 1024
40
#define MEM_RANGE_CHUNK_SZ 2048 /* Initial num dwords for mem ranges */
42
42
static char pathname[MAXPATH], *pathstart;
43
43
static char propnames[NAMESPACE] = { 0 };
44
static unsigned dtstruct[TREEWORDS] __attribute__ ((aligned (8))), *dt;
44
static unsigned *dt_base, *dt;
45
static unsigned int dt_cur_size;
45
46
static unsigned long long mem_rsrv[2*MEMRESERVE] = { 0, 0 };
47
48
static int crash_param = 0;
48
49
static char local_cmdline[COMMAND_LINE_SIZE] = { "" };
49
50
extern mem_rgns_t usablemem_rgns;
50
51
static struct bootblock bb[1];
54
/* Before we add something to the dt, reserve N words using this.
55
* If there isn't enough room, it's realloced -- and you don't overflow and
56
* splat bits of your heap.
58
void dt_reserve(unsigned **dt_ptr, unsigned words)
60
if (((*dt_ptr - dt_base) + words) >= dt_cur_size) {
62
unsigned int new_size = dt_cur_size + INIT_TREE_WORDS;
63
unsigned *new_dt = realloc(dt_base, new_size*4);
66
die("unrecoverable error: Can't realloc %d bytes for "
67
"device tree\n", new_size*4);
68
offset = *dt_ptr - dt_base;
70
dt_cur_size = new_size;
71
*dt_ptr = dt_base + offset;
72
memset(*dt_ptr, 0, (new_size - offset)*4);
52
76
void reserve(unsigned long long where, unsigned long long length)
125
149
char fname[MAXPATH], *bname;
126
150
uint64_t buf[32];
127
uint64_t ranges[2*MAX_MEMORY_RANGES];
152
int ranges_size = MEM_RANGE_CHUNK_SZ;
128
153
uint64_t base, end, loc_base, loc_end;
129
int range, rlen = 0, i;
130
int rngs_cnt, tmp_indx;
154
size_t i, rngs_cnt, range;
132
158
strcpy(fname, pathname);
133
159
bname = strrchr(fname, '/');
140
166
die("unrecoverable error: error seeking in \"%s\": %s\n",
141
167
pathname, strerror(errno));
169
ranges = malloc(ranges_size*8);
171
die("unrecoverable error: can't alloc %d bytes for ranges.\n",
144
175
for (i = 0; i < num_of_lmbs; i++) {
145
176
if (read(fd, buf, 24) < 0)
157
188
for (range = 0; range < usablemem_rgns.size; range++) {
158
190
loc_base = usablemem_rgns.ranges[range].start;
159
191
loc_end = usablemem_rgns.ranges[range].end;
160
192
if (loc_base >= base && loc_end <= end) {
161
ranges[rlen++] = loc_base;
162
ranges[rlen++] = loc_end - loc_base;
164
194
} else if (base < loc_end && end > loc_base) {
165
195
if (loc_base < base)
167
197
if (loc_end > end)
203
if (rlen >= (ranges_size-2)) {
204
ranges_size += MEM_RANGE_CHUNK_SZ;
205
ranges = realloc(ranges, ranges_size*8);
207
die("unrecoverable error: can't"
208
" realloc %d bytes for"
169
212
ranges[rlen++] = loc_base;
170
213
ranges[rlen++] = loc_end - loc_base;
174
/* Store the count of (base, size) duple */
175
ranges[tmp_indx] = rngs_cnt;
218
/* We still need to add a counter for every LMB because
219
* the kernel parsing code is dumb. We just have
220
* a zero in this case, with no following base/len.
222
ranges[tmp_indx] = 0;
223
/* rlen is already just tmp_indx+1 as we didn't write
224
* anything. Check array size here, as we'll probably
225
* go on for a while writing zeros now.
227
if (rlen >= (ranges_size-1)) {
228
ranges_size += MEM_RANGE_CHUNK_SZ;
229
ranges = realloc(ranges, ranges_size*8);
231
die("unrecoverable error: can't"
232
" realloc %d bytes for"
237
/* Store the count of (base, size) duple */
238
ranges[tmp_indx] = rngs_cnt;
178
242
rlen = rlen * sizeof(uint64_t);
180
244
* Add linux,drconf-usable-memory property.
246
dt_reserve(&dt, 4+((rlen + 3)/4));
184
249
*dt++ = propnum("linux,drconf-usable-memory");
185
250
if ((rlen >= 8) && ((unsigned long)dt & 0x4))
187
memcpy(dt, &ranges, rlen);
252
memcpy(dt, ranges, rlen);
188
254
dt += (rlen + 3)/4;
191
static void add_usable_mem_property(int fd, int len)
257
static void add_usable_mem_property(int fd, size_t len)
193
259
char fname[MAXPATH], *bname;
195
uint64_t ranges[2*MAX_MEMORY_RANGES];
262
int ranges_size = MEM_RANGE_CHUNK_SZ;
196
263
uint64_t base, end, loc_base, loc_end;
199
268
strcpy(fname, pathname);
200
269
bname = strrchr(fname,'/');
206
275
if (len < 2 * sizeof(uint64_t))
207
276
die("unrecoverable error: not enough data for mem property\n");
208
len = 2 * sizeof(uint64_t);
277
slen = 2 * sizeof(uint64_t);
210
279
if (lseek(fd, 0, SEEK_SET) < 0)
211
280
die("unrecoverable error: error seeking in \"%s\": %s\n",
212
281
pathname, strerror(errno));
213
if (read(fd, buf, len) != len)
282
if (read(fd, buf, slen) != slen)
214
283
die("unrecoverable error: error reading \"%s\": %s\n",
215
284
pathname, strerror(errno));
220
289
end = base + buf[1];
291
ranges = malloc(ranges_size*8);
293
die("unrecoverable error: can't alloc %d bytes for ranges.\n",
222
296
for (range = 0; range < usablemem_rgns.size; range++) {
223
298
loc_base = usablemem_rgns.ranges[range].start;
224
299
loc_end = usablemem_rgns.ranges[range].end;
225
300
if (loc_base >= base && loc_end <= end) {
226
ranges[rlen++] = loc_base;
227
ranges[rlen++] = loc_end - loc_base;
228
302
} else if (base < loc_end && end > loc_base) {
229
303
if (loc_base < base)
231
305
if (loc_end > end)
310
if (rlen >= (ranges_size-2)) {
311
ranges_size += MEM_RANGE_CHUNK_SZ;
312
ranges = realloc(ranges, ranges_size*8);
314
die("unrecoverable error: can't realloc"
315
"%d bytes for ranges.\n",
233
318
ranges[rlen++] = loc_base;
234
319
ranges[rlen++] = loc_end - loc_base;
250
335
* No add linux,usable-memory property.
337
dt_reserve(&dt, 4+((rlen + 3)/4));
254
340
*dt++ = propnum("linux,usable-memory");
255
341
if ((rlen >= 8) && ((unsigned long)dt & 0x4))
257
memcpy(dt,&ranges,rlen);
343
memcpy(dt, ranges, rlen);
258
345
dt += (rlen + 3)/4;
323
413
die("unrecoverable error: could not open \"%s\": %s\n",
324
414
pathname, strerror(errno));
326
if (read(fd, dt, len) != len)
416
slen = read(fd, dt, len);
327
418
die("unrecoverable error: could not read \"%s\": %s\n",
328
419
pathname, strerror(errno));
420
if ((size_t)slen != len)
421
die("unrecoverable error: short read from\"%s\"\n",
330
424
checkprop(fn, dt, len);
347
441
* Compare function used to sort the device-tree directories
348
442
* This function will be passed to scandir.
350
static int comparefunc(const void *dentry1, const void *dentry2)
444
static int comparefunc(const struct dirent **dentry1,
445
const struct dirent **dentry2)
352
447
char *str1 = (*(struct dirent **)dentry1)->d_name;
353
448
char *str2 = (*(struct dirent **)dentry2)->d_name;
377
472
struct dirent **namelist;
379
474
struct stat statbuf;
477
plen = *pathstart ? strlen(pathstart) : 1;
478
/* Reserve space for string packed to words; e.g. string length 10
479
* occupies 3 words, length 12 occupies 4 (for terminating \0s).
480
* So round up & include the \0:
482
dt_reserve(&dt, 1+((plen + 4)/4));
382
484
strcpy((void *)dt, *pathstart ? pathstart : "/");
485
dt += ((plen + 4)/4);
388
487
numlist = scandir(pathname, &namelist, 0, comparefunc);
483
587
dt += (cmd_len + 3)/4;
485
589
fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
592
* Determine the platform type/stdout type, so that purgatory
593
* code can print 'I'm in purgatory' message. Currently only
594
* pseries/hvcterminal is supported.
596
strcpy(filename, pathname);
597
strncat(filename, "linux,stdout-path", MAXPATH);
598
fd = open(filename, O_RDONLY);
600
printf("Unable to find %s, printing from purgatory is diabled\n",
604
if (fstat(fd, &statbuf)) {
605
printf("Unable to stat %s, printing from purgatory is diabled\n",
612
buff = malloc(statbuf.st_size);
614
printf("Can not allocate memory for buff\n");
618
read(fd, buff, statbuf.st_size);
620
strncpy(filename, "/proc/device-tree/", MAXPATH);
621
strncat(filename, buff, MAXPATH);
622
strncat(filename, "/compatible", MAXPATH);
623
fd = open(filename, O_RDONLY);
625
printf("Unable to find %s printing from purgatory is diabled\n",
629
if (fstat(fd, &statbuf)) {
630
printf("Unable to stat %s printing from purgatory is diabled\n",
635
buff = realloc(buff, statbuf.st_size);
637
printf("Can not allocate memory for buff\n");
641
read(fd, buff, statbuf.st_size);
642
if (!strcmp(buff, "hvterm1") || !strcmp(buff, "hvterm-protocol"))
488
649
for (i=0; i < numlist; i++) {
489
650
dp = namelist[i];
490
651
strcpy(dn, dp->d_name);
518
680
strcpy(pathname, "/proc/device-tree/");
520
682
pathstart = pathname + strlen(pathname);
684
dt_cur_size = INIT_TREE_WORDS;
685
dt_base = malloc(dt_cur_size*4);
687
die("Can't malloc %d bytes for dt struct!\n", dt_cur_size*4);
689
memset(dt_base, 0, dt_cur_size*4);
524
694
strcpy(local_cmdline, cmdline);
529
700
len = sizeof(bb[0]);
558
729
tlen = bb->off_mem_rsvmap;
559
730
memcpy(buf+tlen, mem_rsrv, bb->off_dt_struct - bb->off_mem_rsvmap);
560
731
tlen = tlen + (bb->off_dt_struct - bb->off_mem_rsvmap);
561
memcpy(buf+tlen, dtstruct, bb->off_dt_strings - bb->off_dt_struct);
732
memcpy(buf+tlen, dt_base, bb->off_dt_strings - bb->off_dt_struct);
562
733
tlen = tlen + (bb->off_dt_strings - bb->off_dt_struct);
563
734
memcpy(buf+tlen, propnames, bb->totalsize - bb->off_dt_strings);
564
735
tlen = tlen + bb->totalsize - bb->off_dt_strings;