1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
#include "atags.h"
#include "io.h"
static inline struct atag_header *next_tag(struct atag_header *tag)
{
return (struct atag_header*) (((uint32_t*) tag) + tag->size);
}
#define TAG_CONTENTS_FUN(tagname) \
static inline struct atag_##tagname *tagname##_tag_contents \
(struct atag_header *tag) \
{ \
return (struct atag_##tagname*) (tag + 1); \
}
TAG_CONTENTS_FUN(header)
TAG_CONTENTS_FUN(core)
TAG_CONTENTS_FUN(mem)
TAG_CONTENTS_FUN(videotext)
TAG_CONTENTS_FUN(ramdisk)
TAG_CONTENTS_FUN(initrd2)
TAG_CONTENTS_FUN(serialnr)
TAG_CONTENTS_FUN(revision)
TAG_CONTENTS_FUN(videolfb)
TAG_CONTENTS_FUN(cmdline)
uint32_t find_memory_size(struct atag_header *atags)
{
// we silently assume there will only be one mem atag
while (atags->tag != ATAG_MEM && atags->tag != ATAG_NONE)
atags = next_tag(atags);
if (atags->tag == ATAG_NONE)
return 0;
struct atag_mem *mem_tag = mem_tag_contents(atags);
// our design assumes address 0x0 is available, so we reject mem
// atag saying otherwise
if (mem_tag->start != 0)
{
puts("ignoring information about memory, "
"that doesn't start at 0x0");
return 0;
}
return mem_tag->size;
}
void print_tag(struct atag_header *tag)
{
#define TAG_CASE(tagname_upcase, tagname_locase, instructions) \
case ATAG_##tagname_upcase: \
puts("ATAG_" #tagname_upcase ":"); \
{ \
struct atag_##tagname_locase *contents = \
tagname_locase##_tag_contents(tag); \
instructions; \
} \
break
switch (tag->tag)
{
TAG_CASE(CORE, core,
prints(" flags: 0x");
printhex(contents->flags); puts("");
prints(" page size: ");
printdec(contents->pagesize); puts("");
prints(" root device: ");
printdec(contents->rootdev); puts(""););
TAG_CASE(MEM, mem,
prints(" memory size: 0x");
printhex(contents->size); puts("");
prints(" memory start: 0x");
printhex(contents->start); puts(""););
// the rest are unimportant for now,
// as they're not passed by qemu
TAG_CASE(VIDEOTEXT, videotext, (void) contents;);
TAG_CASE(RAMDISK, ramdisk, (void) contents;);
TAG_CASE(INITRD2, initrd2, (void) contents;);
TAG_CASE(SERIAL, serialnr, (void) contents;);
TAG_CASE(REVISION, revision, (void) contents;);
TAG_CASE(VIDEOLFB, videolfb, (void) contents;);
TAG_CASE(CMDLINE, cmdline, (void) contents;);
case ATAG_NONE:
puts("ATAG_NONE");
break;
default:
prints("!! unknown tag: 0x"); printhex(tag->tag); puts(" !!");
}
}
void print_atags(struct atag_header *atags)
{
while (atags->tag != ATAG_NONE)
{
print_tag(atags);
atags = next_tag(atags);
}
print_tag(atags); // also print ATAG_NONE
}
|