aboutsummaryrefslogtreecommitdiff
path: root/atags.c
diff options
context:
space:
mode:
authorvetch <vetch97@gmail.com>2020-01-02 17:54:31 +0100
committervetch <vetch97@gmail.com>2020-01-02 17:54:31 +0100
commitab7b754bb32022336527c1a2d5d710b95a589d0e (patch)
tree19f508f06c72efcbdd2cfad46949ed6f1ae45a3c /atags.c
parent5e1e6796109c892c4300c3da17c35e7874a40107 (diff)
parent6bf5a3b8c6e8a5d1cb3fb4880a5d9688ab094c62 (diff)
downloadrpi-MMU-example-ab7b754bb32022336527c1a2d5d710b95a589d0e.tar.gz
rpi-MMU-example-ab7b754bb32022336527c1a2d5d710b95a589d0e.zip
Merge branch 'bob' of https://repo.or.cz/RPi-MMU-example into alice
# Conflicts: # .gitignore # PL0_test.ld # demo_functionality.c # interrupt_vector.S # interrupts.c # kernel.c # memory.h
Diffstat (limited to 'atags.c')
-rw-r--r--atags.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/atags.c b/atags.c
new file mode 100644
index 0000000..e2e6a24
--- /dev/null
+++ b/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
+}