coreboot/util/nvramtool/cbfs.c
<<
>>
Prefs
   1/*
   2 * This file is part of the coreboot project.
   3 *
   4 * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
   5 * Copyright (C) 2011 secunet Security Networks AG
   6 *     (Written by Patrick Georgi <patrick.georgi@secunet.com>)
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; version 2 of the License.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
  20 */
  21
  22#include <arpa/inet.h>
  23#include <sys/types.h>
  24#include <sys/stat.h>
  25#include <sys/mman.h>
  26#include <stdlib.h>
  27#include <fcntl.h>
  28#include <string.h>
  29#include <stdio.h>
  30#include "cbfs.h"
  31
  32#define ALIGN(x,a)              __ALIGN_MASK(x,(typeof(x))(a)-1)
  33#define __ALIGN_MASK(x,mask)    (((x)+(mask))&~(mask))
  34
  35static void *cbfs_mapped;
  36static u32 cbfs_offset;
  37static void* virt_to_phys(u32 virt)
  38{
  39        return (void*)(virt+cbfs_offset);
  40}
  41
  42#ifdef DEBUG
  43#define debug(x...) printf(x)
  44#else
  45#define debug(x...) while(0) {}
  46#endif
  47
  48static int cbfs_check_magic(struct cbfs_file *file)
  49{
  50        return !strcmp(file->magic, CBFS_FILE_MAGIC) ? 1 : 0;
  51}
  52
  53static struct cbfs_header *cbfs_master_header(void)
  54{
  55        struct cbfs_header *header;
  56
  57        void *ptr = virt_to_phys(*((u32*)virt_to_phys(CBFS_HEADPTR_ADDR)));
  58        debug("Check CBFS header at %p\n", ptr);
  59        header = (struct cbfs_header *) ptr;
  60
  61        debug("magic is %08x\n", ntohl(header->magic));
  62        if (ntohl(header->magic) != CBFS_HEADER_MAGIC) {
  63                printf("ERROR: No valid CBFS header found!\n");
  64                return NULL;
  65        }
  66
  67        debug("Found CBFS header at %p\n", ptr);
  68        return header;
  69}
  70
  71struct cbfs_file *cbfs_find(const char *name)
  72{
  73        struct cbfs_header *header = cbfs_master_header();
  74        unsigned long offset;
  75
  76        if (header == NULL)
  77                return NULL;
  78        offset = (u32)virt_to_phys(0 - ntohl(header->romsize) + ntohl(header->offset));
  79
  80        int align= ntohl(header->align);
  81
  82        while(1) {
  83                struct cbfs_file *file = (struct cbfs_file *) offset;
  84                if (!cbfs_check_magic(file)) return NULL;
  85                debug("Check %s\n", CBFS_NAME(file));
  86                if (!strcmp(CBFS_NAME(file), name))
  87                        return file;
  88
  89                int flen = ntohl(file->len);
  90                int foffset = ntohl(file->offset);
  91                debug("CBFS: follow chain: %p + %x + %x + align -> ", (void *)offset, foffset, flen);
  92
  93                unsigned long oldoffset = offset;
  94                offset = ALIGN(offset + foffset + flen, align);
  95                debug("%p\n", (void *)offset);
  96                if (offset <= oldoffset) return NULL;
  97
  98                if (offset < (u32)virt_to_phys(0xFFFFFFFF - ntohl(header->romsize)))
  99                        return NULL;
 100        }
 101}
 102
 103void *cbfs_find_file(const char *name, unsigned int type, unsigned int *len)
 104{
 105        struct cbfs_file *file = cbfs_find(name);
 106
 107        if (file == NULL) {
 108                printf("CBFS:  Could not find file %s\n",
 109                       name);
 110                return NULL;
 111        }
 112
 113        if (ntohl(file->type) != type) {
 114                printf("CBFS:  File %s is of type %x instead of"
 115                       "type %x\n", name, file->type, type);
 116
 117                return NULL;
 118        }
 119        if (len != NULL) *len = file->len;
 120
 121        return (void *) CBFS_SUBHEADER(file);
 122}
 123
 124void open_cbfs(const char *filename)
 125{
 126        struct stat cbfs_stat;
 127        int cbfs_fd;
 128
 129        cbfs_fd = open(filename, O_RDWR);
 130        if (cbfs_fd == -1) {
 131                printf("Couldn't open '%s'\n", filename);
 132                exit(-1);
 133        }
 134        if (fstat(cbfs_fd, &cbfs_stat) == -1) {
 135                printf("Couldn't stat '%s'\n", filename);
 136                exit(-1);
 137        }
 138        cbfs_mapped = mmap(NULL, cbfs_stat.st_size, PROT_READ | PROT_WRITE,
 139                        MAP_SHARED, cbfs_fd, 0);
 140        if (cbfs_mapped == MAP_FAILED) {
 141                printf("Couldn't map '%s'\n", filename);
 142                exit(-1);
 143        }
 144        cbfs_offset = (uint32_t)cbfs_mapped-(0xffffffff-cbfs_stat.st_size+1);
 145}
 146
 147
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.