aboutsummaryrefslogtreecommitdiff
path: root/src/arm/PL1/kernel/atags.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arm/PL1/kernel/atags.c')
-rw-r--r--src/arm/PL1/kernel/atags.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/arm/PL1/kernel/atags.c b/src/arm/PL1/kernel/atags.c
new file mode 100644
index 0000000..e2e6a24
--- /dev/null
+++ b/src/arm/PL1/kernel/atags.c
@@ -0,0 +1,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
+}