#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 }