/* Copyright (C) 2012, Aaron Lindsay This file is part of Aedrix. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include extern arch_uint_ptr atags_ptr; int atag_valid(struct atag *a) { switch (a->tag) { case ATAG_NONE: return a->size == 2; case ATAG_CORE: return a->size == 2 || a->size == 5; case ATAG_MEM: case ATAG_INITRD2: case ATAG_SERIAL: return a->size == 4; case ATAG_VIDEOTEXT: case ATAG_RAMDISK: return a->size == 5; case ATAG_REVISION: return a->size == 3; case ATAG_VIDEOLFB: return a->size == 8; case ATAG_CMDLINE: return a->size >= 3; default: return 0; } } int _atags_mem_region(struct atag **mem_header, int initialize) { if (initialize) *mem_header = (struct atag *)atags_ptr; else *mem_header = (struct atag *)((uint32 *)*mem_header + (*mem_header)->size); while (atag_valid(*mem_header) && (*mem_header)->tag != ATAG_NONE && (*mem_header)->tag != ATAG_MEM) { *mem_header = (struct atag *)((uint32 *)*mem_header + (*mem_header)->size); } if (!atag_valid(*mem_header) || (*mem_header)->tag == ATAG_NONE) return -1; return 0; } int detect_memory() { struct atag *atags; char *lower, *upper; if (atags_first_mem_region(&atags)) { return -1; } do { lower = (char *)atags->data.mem.start; upper = lower + atags->data.mem.size - 1; declare_memory_region(lower, upper); } while (!atags_next_mem_region(&atags)); return 0; }