2 * This file is part of the coreboot project.
4 * Copyright 2012-2015 Google Inc.
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.
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.
16 #include <arch/early_variables.h>
17 #include <boot_device.h>
18 #include <console/console.h>
20 #include <commonlib/fmap_serialized.h>
24 #include "fmap_config.h"
27 * See http://code.google.com/p/flashmap/ for more information on FMAP.
30 static int fmap_print_once CAR_GLOBAL
;
32 int find_fmap_directory(struct region_device
*fmrd
)
34 const struct region_device
*boot
;
37 size_t offset
= FMAP_OFFSET
;
40 boot
= boot_device_ro();
45 fmap_size
= sizeof(struct fmap
);
47 fmap
= rdev_mmap(boot
, offset
, fmap_size
);
52 if (memcmp(fmap
->signature
, FMAP_SIGNATURE
, sizeof(fmap
->signature
))) {
53 printk(BIOS_DEBUG
, "No FMAP found at %zx offset.\n", offset
);
54 rdev_munmap(boot
, fmap
);
58 if (!car_get_var(fmap_print_once
)) {
59 printk(BIOS_DEBUG
, "FMAP: Found \"%s\" version %d.%d at %zx.\n",
60 fmap
->name
, fmap
->ver_major
, fmap
->ver_minor
, offset
);
61 printk(BIOS_DEBUG
, "FMAP: base = %llx size = %x #areas = %d\n",
62 (long long)fmap
->base
, fmap
->size
, fmap
->nareas
);
63 car_set_var(fmap_print_once
, 1);
66 fmap_size
+= fmap
->nareas
* sizeof(struct fmap_area
);
68 rdev_munmap(boot
, fmap
);
70 return rdev_chain(fmrd
, boot
, offset
, fmap_size
);
73 int fmap_locate_area_as_rdev(const char *name
, struct region_device
*area
)
77 if (fmap_locate_area(name
, &ar
))
80 return boot_device_ro_subregion(&ar
, area
);
83 int fmap_locate_area_as_rdev_rw(const char *name
, struct region_device
*area
)
87 if (fmap_locate_area(name
, &ar
))
90 return boot_device_rw_subregion(&ar
, area
);
93 int fmap_locate_area(const char *name
, struct region
*ar
)
95 struct region_device fmrd
;
98 if (find_fmap_directory(&fmrd
))
101 /* Start reading the areas just after fmap header. */
102 offset
= sizeof(struct fmap
);
105 struct fmap_area
*area
;
107 area
= rdev_mmap(&fmrd
, offset
, sizeof(*area
));
112 if (strcmp((const char *)area
->name
, name
)) {
113 rdev_munmap(&fmrd
, area
);
114 offset
+= sizeof(struct fmap_area
);
118 printk(BIOS_DEBUG
, "FMAP: area %s found @ %x (%d bytes)\n",
119 name
, area
->offset
, area
->size
);
121 ar
->offset
= area
->offset
;
122 ar
->size
= area
->size
;
124 rdev_munmap(&fmrd
, area
);
129 printk(BIOS_DEBUG
, "FMAP: area %s not found\n", name
);
134 int fmap_find_region_name(const struct region
* const ar
,
135 char name
[FMAP_STRLEN
])
137 struct region_device fmrd
;
140 if (find_fmap_directory(&fmrd
))
143 /* Start reading the areas just after fmap header. */
144 offset
= sizeof(struct fmap
);
147 struct fmap_area
*area
;
149 area
= rdev_mmap(&fmrd
, offset
, sizeof(*area
));
154 if ((ar
->offset
!= area
->offset
) ||
155 (ar
->size
!= area
->size
)) {
156 rdev_munmap(&fmrd
, area
);
157 offset
+= sizeof(struct fmap_area
);
161 printk(BIOS_DEBUG
, "FMAP: area (%zx, %zx) found, named %s\n",
162 ar
->offset
, ar
->size
, area
->name
);
164 memcpy(name
, area
->name
, FMAP_STRLEN
);
166 rdev_munmap(&fmrd
, area
);
171 printk(BIOS_DEBUG
, "FMAP: area (%zx, %zx) not found\n",
172 ar
->offset
, ar
->size
);