coreboot-kgpe-d16/util/cbfstool/fmap_from_fmd.c
Hung-Te Lin 49a4450563 cbfstool: Support new FMD flag "PRESERVE"
When updating firmware, it is very often that we may want to preserve
few sections, for example vital product data (VPD) including serial
number, calibration data and cache. A firmware updater has to hard-code
the section names that need to be preserved and is hard to maintain.

A better approach is to specify that in FMAP area flags (the `area_flag`
field) using FMAP_AREA_PRESERVE. With this patchset, a FMD parser flag
"PRESERVE" is introduced and will be converted to FMAP_AREA_PRESERVE
when generating FMAP data (by fmap_from_fmd.c).

For example, The FMD statement:

  RO_VPD(PRESERVE)@0x0 16k

will generate an FMAP firmware section that:

  area_name = "RO_VPD"
  area_offset = 0
  area_size = 16384
  area_flags = FMAP_AREA_PRESERVE

BUG=chromium:936768
TEST=make; boots on x86 "google/eve" and arm "google/kukui" devices
     Manually added 'PRESERVE' to some FMD files, and verify (by running
     fmap.py) the output coreboot.rom has FMAP_AREA_PRESERVE set

Change-Id: I51e7d31029b98868a1cab0d26bf04a14db01b1c0
Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/31707
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
2019-03-05 20:51:39 +00:00

80 lines
2.1 KiB
C

/*
* fmap_from_fmd.c, tool to distill flashmap descriptors into raw FMAP sections
*
* Copyright (C) 2015 Google, Inc.
*
* 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; version 2 of the License.
*
* 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.
*/
#include "fmap_from_fmd.h"
#include "common.h"
#include <assert.h>
#include <string.h>
static bool fmap_append_fmd_node(struct fmap **flashmap,
const struct flashmap_descriptor *section,
unsigned absolute_watermark) {
uint16_t flags = 0;
if (strlen(section->name) >= FMAP_STRLEN) {
ERROR("Section name ('%s') exceeds %d character FMAP format limit\n",
section->name, FMAP_STRLEN - 1);
return false;
}
absolute_watermark += section->offset;
if (section->flags.f.preserve)
flags |= FMAP_AREA_PRESERVE;
if (fmap_append_area(flashmap, absolute_watermark, section->size,
(uint8_t *)section->name, flags) < 0) {
ERROR("Failed to insert section '%s' into FMAP\n",
section->name);
return false;
}
fmd_foreach_child(subsection, section) {
if (!fmap_append_fmd_node(flashmap, subsection,
absolute_watermark))
return false;
}
return true;
}
struct fmap *fmap_from_fmd(const struct flashmap_descriptor *desc)
{
assert(desc);
assert(desc->size_known);
if (strlen(desc->name) >= FMAP_STRLEN) {
ERROR("Image name ('%s') exceeds %d character FMAP header limit\n",
desc->name, FMAP_STRLEN - 1);
return NULL;
}
struct fmap *fmap = fmap_create(desc->offset_known ? desc->offset : 0,
desc->size, (uint8_t *)desc->name);
if (!fmap) {
ERROR("Failed to allocate FMAP header\n");
return fmap;
}
fmd_foreach_child(real_section, desc) {
if (!fmap_append_fmd_node(&fmap, real_section, 0)) {
fmap_destroy(fmap);
return NULL;
}
}
return fmap;
}