blob: dea34bc02bdd0d7a925e1eaa8f6f9f5aae226ce4 [file] [log] [blame]
Aaron Durbin0424c952015-03-28 23:56:22 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2012-2015 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.
18 */
19
20#include <boot_device.h>
21#include <console/console.h>
22#include <fmap.h>
23#include <fmap_serialized.h>
24#include <stddef.h>
25#include <string.h>
26
27/*
28 * See http://code.google.com/p/flashmap/ for more information on FMAP.
29 */
30
Patrick Georgi977587a2015-07-09 13:34:40 +020031int find_fmap_directory(struct region_device *fmrd)
Aaron Durbin0424c952015-03-28 23:56:22 -050032{
33 const struct region_device *boot;
34 struct fmap *fmap;
35 size_t fmap_size;
36 size_t offset = CONFIG_FLASHMAP_OFFSET;
37
38 boot_device_init();
39 boot = boot_device_ro();
40
41 if (boot == NULL)
42 return -1;
43
44 fmap_size = sizeof(struct fmap);
45
46 fmap = rdev_mmap(boot, offset, fmap_size);
47
48 if (fmap == NULL)
49 return -1;
50
51 if (memcmp(fmap->signature, FMAP_SIGNATURE, sizeof(fmap->signature))) {
52 printk(BIOS_DEBUG, "No FMAP found at %zx offset.\n", offset);
53 rdev_munmap(boot, fmap);
54 return -1;
55 }
56
57 printk(BIOS_DEBUG, "FMAP: Found \"%s\" version %d.%d at %zx.\n",
58 fmap->name, fmap->ver_major, fmap->ver_minor, offset);
59 printk(BIOS_DEBUG, "FMAP: base = %llx size = %x #areas = %d\n",
60 (long long)fmap->base, fmap->size, fmap->nareas);
61
62 fmap_size += fmap->nareas * sizeof(struct fmap_area);
63
64 rdev_munmap(boot, fmap);
65
66 return rdev_chain(fmrd, boot, offset, fmap_size);
67}
68
69int fmap_locate_area_as_rdev(const char *name, struct region_device *area)
70{
71 struct region ar;
72
73 if (fmap_locate_area(name, &ar))
74 return -1;
75
76 return boot_device_ro_subregion(&ar, area);
77}
78
79int fmap_locate_area(const char *name, struct region *ar)
80{
81 struct region_device fmrd;
82 size_t offset;
83
84 if (find_fmap_directory(&fmrd))
85 return -1;
86
87 /* Start reading the areas just after fmap header. */
88 offset = sizeof(struct fmap);
89
90 while (1) {
91 struct fmap_area *area;
92
93 area = rdev_mmap(&fmrd, offset, sizeof(*area));
94
95 if (area == NULL)
96 return -1;
97
98 if (strcmp((const char *)area->name, name)) {
99 rdev_munmap(&fmrd, area);
100 offset += sizeof(struct fmap_area);
101 continue;
102 }
103
104 printk(BIOS_DEBUG, "FMAP: area %s found\n", name);
105 printk(BIOS_DEBUG, "FMAP: offset: %x\n", area->offset);
106 printk(BIOS_DEBUG, "FMAP: size: %d bytes\n", area->size);
107
108 ar->offset = area->offset;
109 ar->size = area->size;
110
111 rdev_munmap(&fmrd, area);
112
113 return 0;
114 }
115
116 printk(BIOS_DEBUG, "FMAP: area %s not found\n", name);
117
118 return -1;
119}
Patrick Georgi99526902015-07-09 11:27:44 +0200120
121int fmap_find_region_name(const struct region * const ar,
122 char name[FMAP_STRLEN])
123{
124 struct region_device fmrd;
125 size_t offset;
126
127 if (find_fmap_directory(&fmrd))
128 return -1;
129
130 /* Start reading the areas just after fmap header. */
131 offset = sizeof(struct fmap);
132
133 while (1) {
134 struct fmap_area *area;
135
136 area = rdev_mmap(&fmrd, offset, sizeof(*area));
137
138 if (area == NULL)
139 return -1;
140
141 if ((ar->offset != area->offset) ||
142 (ar->size != area->size)) {
143 rdev_munmap(&fmrd, area);
144 offset += sizeof(struct fmap_area);
145 continue;
146 }
147
148 printk(BIOS_DEBUG, "FMAP: area (%zx, %zx) found, named %s\n",
149 ar->offset, ar->size, area->name);
150
151 memcpy(name, area->name, FMAP_STRLEN);
152
153 rdev_munmap(&fmrd, area);
154
155 return 0;
156 }
157
158 printk(BIOS_DEBUG, "FMAP: area (%zx, %zx) not found\n",
159 ar->offset, ar->size);
160
161 return -1;
162}