Files
s390-tools/genprotimg/src/pv/pv_ipib.c
T
Marc Hartmayer b6bdd7744a genprotimg: use pv_ namespace for our Buffer implementation
Use `pv_` namespace for our Buffer implementation so a symbol clash with other
libraries is less likely.

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/109
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2021-02-24 18:33:44 +01:00

129 lines
3.3 KiB
C

/*
* PV IPIB related definitions and functions
*
* Copyright IBM Corp. 2020
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <glib.h>
#include <glib/gtypes.h>
#include <stdint.h>
#include <stdio.h>
#include "boot/ipl.h"
#include "boot/s390.h"
#include "common.h"
#include "include/pv_hdr_def.h"
#include "lib/zt_common.h"
#include "utils/align.h"
#include "utils/buffer.h"
#include "pv_comp.h"
#include "pv_error.h"
#include "pv_ipib.h"
uint64_t pv_ipib_get_size(uint32_t num_comp)
{
gsize ipib_size = sizeof(struct ipl_pl_hdr) +
sizeof(struct ipl_pb0_pv) +
num_comp * sizeof(struct ipl_pb0_pv_comp);
/* the minimal size is one page */
return MAX(ipib_size, PAGE_SIZE);
}
static gint pv_ipib_init(IplParameterBlock *ipib, GSList *comps,
const PvBuffer *hdr)
{
g_assert(sizeof(struct ipl_pl_hdr) <= UINT32_MAX);
g_assert(sizeof(struct ipl_pb0_pv_comp) <= UINT32_MAX);
g_assert(sizeof(struct ipl_pb0_pv) <= UINT32_MAX);
g_assert(ipib);
guint comps_length = g_slist_length(comps);
uint32_t ipl_pl_hdr_size = (uint32_t)sizeof(struct ipl_pl_hdr);
struct ipl_pb0_pv *pv = &ipib->pv;
uint32_t ipib_comps_size;
uint32_t blk0_len;
uint32_t ipib_size;
gsize i;
g_assert_true(
g_uint_checked_mul(&ipib_comps_size, comps_length,
(uint32_t)sizeof(struct ipl_pb0_pv_comp)));
g_assert_true(g_uint_checked_add(&blk0_len, (uint32_t)sizeof(*pv),
ipib_comps_size));
g_assert(ipl_pl_hdr_size + blk0_len <= PAGE_SIZE);
ipib_size = MAX(ipl_pl_hdr_size + blk0_len, (uint32_t)PAGE_SIZE);
g_assert(pv_ipib_get_size(comps_length) == ipib_size);
pv->pbt = IPL_TYPE_PV;
pv->len = GUINT32_TO_BE(blk0_len);
pv->num_comp = GUINT32_TO_BE(comps_length);
/* both values will be overwritten during the IPL process by
* the stage3a loader
*/
pv->pv_hdr_addr = GUINT64_TO_BE(0x0);
pv->pv_hdr_size = GUINT64_TO_BE(hdr->size);
ipib->hdr.len = GUINT32_TO_BE(ipib_size);
ipib->hdr.version = IPL_PARM_BLOCK_VERSION;
i = 0;
for (GSList *iterator = comps; iterator; iterator = iterator->next, i++) {
const PvComponent *comp = iterator->data;
uint64_t comp_addr, comp_size;
g_assert(comp);
comp_addr = pv_component_get_src_addr(comp);
comp_size = pv_component_size(comp);
g_assert(IS_PAGE_ALIGNED(comp_size));
pv->components[i].addr = GUINT64_TO_BE(comp_addr);
pv->components[i].len = GUINT64_TO_BE(comp_size);
pv->components[i].tweak_pref =
GUINT64_TO_BE(pv_component_get_tweak_prefix(comp));
if (i > 0) {
/* tweak prefixes of the components must grow
* strictly monotonous
*/
g_assert(GUINT64_FROM_BE(pv->components[i].tweak_pref) >
GUINT64_FROM_BE(pv->components[i - 1].tweak_pref));
}
}
return 0;
}
IplParameterBlock *pv_ipib_new(GSList *comps, const PvBuffer *hdr, GError **err)
{
uint64_t ipib_size = pv_ipib_get_size(g_slist_length(comps));
g_autoptr(IplParameterBlock) ret = NULL;
if (ipib_size > PV_V1_IPIB_MAX_SIZE) {
g_set_error(err, PV_ERROR, PV_ERROR_IPIB_SIZE,
_("IPIB size is too large: %lu < %lu"), ipib_size,
PAGE_SIZE);
return NULL;
}
ret = g_malloc0(ipib_size);
if (pv_ipib_init(ret, comps, hdr) < 0)
return NULL;
return g_steal_pointer(&ret);
}
void pv_ipib_free(IplParameterBlock *ipib)
{
if (!ipib)
return;
g_free(ipib);
}