blob: 028bc2538beb8d88ec00eb76bc7f63da6b6499ff [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.
Aaron Durbin0424c952015-03-28 23:56:22 -050014 */
15
16#include <boot_device.h>
17#include <console/console.h>
18#include <fmap.h>
Aaron Durbindc9f5cd2015-09-08 13:34:43 -050019#include <commonlib/fmap_serialized.h>
Aaron Durbin0424c952015-03-28 23:56:22 -050020#include <stddef.h>
21#include <string.h>
22
23/*
24 * See http://code.google.com/p/flashmap/ for more information on FMAP.
25 */
26
Patrick Georgi977587a2015-07-09 13:34:40 +020027int find_fmap_directory(struct region_device *fmrd)
Aaron Durbin0424c952015-03-28 23:56:22 -050028{
29 const struct region_device *boot;
30 struct fmap *fmap;
31 size_t fmap_size;
32 size_t offset = CONFIG_FLASHMAP_OFFSET;
33
34 boot_device_init();
35 boot = boot_device_ro();
36
37 if (boot == NULL)
38 return -1;
39
40 fmap_size = sizeof(struct fmap);
41
42 fmap = rdev_mmap(boot, offset, fmap_size);
43
44 if (fmap == NULL)
45 return -1;
46
47 if (memcmp(fmap->signature, FMAP_SIGNATURE, sizeof(fmap->signature))) {
48 printk(BIOS_DEBUG, "No FMAP found at %zx offset.\n", offset);
49 rdev_munmap(boot, fmap);
50 return -1;
51 }
52
53 printk(BIOS_DEBUG, "FMAP: Found \"%s\" version %d.%d at %zx.\n",
54 fmap->name, fmap->ver_major, fmap->ver_minor, offset);
55 printk(BIOS_DEBUG, "FMAP: base = %llx size = %x #areas = %d\n",
56 (long long)fmap->base, fmap->size, fmap->nareas);
57
58 fmap_size += fmap->nareas * sizeof(struct fmap_area);
59
60 rdev_munmap(boot, fmap);
61
62 return rdev_chain(fmrd, boot, offset, fmap_size);
63}
64
65int fmap_locate_area_as_rdev(const char *name, struct region_device *area)
66{
67 struct region ar;
68
69 if (fmap_locate_area(name, &ar))
70 return -1;
71
72 return boot_device_ro_subregion(&ar, area);
73}
74
75int fmap_locate_area(const char *name, struct region *ar)
76{
77 struct region_device fmrd;
78 size_t offset;
79
80 if (find_fmap_directory(&fmrd))
81 return -1;
82
83 /* Start reading the areas just after fmap header. */
84 offset = sizeof(struct fmap);
85
86 while (1) {
87 struct fmap_area *area;
88
89 area = rdev_mmap(&fmrd, offset, sizeof(*area));
90
91 if (area == NULL)
92 return -1;
93
94 if (strcmp((const char *)area->name, name)) {
95 rdev_munmap(&fmrd, area);
96 offset += sizeof(struct fmap_area);
97 continue;
98 }
99
100 printk(BIOS_DEBUG, "FMAP: area %s found\n", name);
101 printk(BIOS_DEBUG, "FMAP: offset: %x\n", area->offset);
102 printk(BIOS_DEBUG, "FMAP: size: %d bytes\n", area->size);
103
104 ar->offset = area->offset;
105 ar->size = area->size;
106
107 rdev_munmap(&fmrd, area);
108
109 return 0;
110 }
111
112 printk(BIOS_DEBUG, "FMAP: area %s not found\n", name);
113
114 return -1;
115}
Patrick Georgi99526902015-07-09 11:27:44 +0200116
117int fmap_find_region_name(const struct region * const ar,
118 char name[FMAP_STRLEN])
119{
120 struct region_device fmrd;
121 size_t offset;
122
123 if (find_fmap_directory(&fmrd))
124 return -1;
125
126 /* Start reading the areas just after fmap header. */
127 offset = sizeof(struct fmap);
128
129 while (1) {
130 struct fmap_area *area;
131
132 area = rdev_mmap(&fmrd, offset, sizeof(*area));
133
134 if (area == NULL)
135 return -1;
136
137 if ((ar->offset != area->offset) ||
138 (ar->size != area->size)) {
139 rdev_munmap(&fmrd, area);
140 offset += sizeof(struct fmap_area);
141 continue;
142 }
143
144 printk(BIOS_DEBUG, "FMAP: area (%zx, %zx) found, named %s\n",
145 ar->offset, ar->size, area->name);
146
147 memcpy(name, area->name, FMAP_STRLEN);
148
149 rdev_munmap(&fmrd, area);
150
151 return 0;
152 }
153
154 printk(BIOS_DEBUG, "FMAP: area (%zx, %zx) not found\n",
155 ar->offset, ar->size);
156
157 return -1;
158}