From 254e035cc27d5787348849b65619a702ae0d42e3 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Tue, 31 Dec 2019 10:42:17 +0100 Subject: handle atags in C code, print (some of) it's contents --- atags.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 atags.c (limited to 'atags.c') diff --git a/atags.c b/atags.c new file mode 100644 index 0000000..9b88724 --- /dev/null +++ b/atags.c @@ -0,0 +1,99 @@ +#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) + 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 +} -- cgit v1.2.3