mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
s390/ipl: add helper functions to create an IPL report
PR: Adjusted to the use in kexec_file later. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Philipp Rudo <prudo@linux.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
9641b8cc73
commit
937347ac56
2 changed files with 161 additions and 0 deletions
|
@ -81,6 +81,33 @@ extern struct ipl_info ipl_info;
|
||||||
extern void setup_ipl(void);
|
extern void setup_ipl(void);
|
||||||
extern void set_os_info_reipl_block(void);
|
extern void set_os_info_reipl_block(void);
|
||||||
|
|
||||||
|
struct ipl_report {
|
||||||
|
struct ipl_parameter_block *ipib;
|
||||||
|
struct list_head components;
|
||||||
|
struct list_head certificates;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipl_report_component {
|
||||||
|
struct list_head list;
|
||||||
|
struct ipl_rb_component_entry entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipl_report_certificate {
|
||||||
|
struct list_head list;
|
||||||
|
struct ipl_rb_certificate_entry entry;
|
||||||
|
void *key;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct kexec_buf;
|
||||||
|
struct ipl_report *ipl_report_init(struct ipl_parameter_block *ipib);
|
||||||
|
void *ipl_report_finish(struct ipl_report *report);
|
||||||
|
int ipl_report_free(struct ipl_report *report);
|
||||||
|
int ipl_report_add_component(struct ipl_report *report, struct kexec_buf *kbuf,
|
||||||
|
unsigned char flags, unsigned short cert);
|
||||||
|
int ipl_report_add_certificate(struct ipl_report *report, void *key,
|
||||||
|
unsigned long addr, unsigned long len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DIAG 308 support
|
* DIAG 308 support
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1705,3 +1705,137 @@ void s390_reset_system(void)
|
||||||
__ctl_clear_bit(0, 28);
|
__ctl_clear_bit(0, 28);
|
||||||
diag308_reset();
|
diag308_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_KEXEC_FILE
|
||||||
|
|
||||||
|
int ipl_report_add_component(struct ipl_report *report, struct kexec_buf *kbuf,
|
||||||
|
unsigned char flags, unsigned short cert)
|
||||||
|
{
|
||||||
|
struct ipl_report_component *comp;
|
||||||
|
|
||||||
|
comp = vzalloc(sizeof(*comp));
|
||||||
|
if (!comp)
|
||||||
|
return -ENOMEM;
|
||||||
|
list_add_tail(&comp->list, &report->components);
|
||||||
|
|
||||||
|
comp->entry.addr = kbuf->mem;
|
||||||
|
comp->entry.len = kbuf->memsz;
|
||||||
|
comp->entry.flags = flags;
|
||||||
|
comp->entry.certificate_index = cert;
|
||||||
|
|
||||||
|
report->size += sizeof(comp->entry);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipl_report_add_certificate(struct ipl_report *report, void *key,
|
||||||
|
unsigned long addr, unsigned long len)
|
||||||
|
{
|
||||||
|
struct ipl_report_certificate *cert;
|
||||||
|
|
||||||
|
cert = vzalloc(sizeof(*cert));
|
||||||
|
if (!cert)
|
||||||
|
return -ENOMEM;
|
||||||
|
list_add_tail(&cert->list, &report->certificates);
|
||||||
|
|
||||||
|
cert->entry.addr = addr;
|
||||||
|
cert->entry.len = len;
|
||||||
|
cert->key = key;
|
||||||
|
|
||||||
|
report->size += sizeof(cert->entry);
|
||||||
|
report->size += cert->entry.len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ipl_report *ipl_report_init(struct ipl_parameter_block *ipib)
|
||||||
|
{
|
||||||
|
struct ipl_report *report;
|
||||||
|
|
||||||
|
report = vzalloc(sizeof(*report));
|
||||||
|
if (!report)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
report->ipib = ipib;
|
||||||
|
INIT_LIST_HEAD(&report->components);
|
||||||
|
INIT_LIST_HEAD(&report->certificates);
|
||||||
|
|
||||||
|
report->size = ALIGN(ipib->hdr.len, 8);
|
||||||
|
report->size += sizeof(struct ipl_rl_hdr);
|
||||||
|
report->size += sizeof(struct ipl_rb_components);
|
||||||
|
report->size += sizeof(struct ipl_rb_certificates);
|
||||||
|
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ipl_report_finish(struct ipl_report *report)
|
||||||
|
{
|
||||||
|
struct ipl_report_certificate *cert;
|
||||||
|
struct ipl_report_component *comp;
|
||||||
|
struct ipl_rb_certificates *certs;
|
||||||
|
struct ipl_parameter_block *ipib;
|
||||||
|
struct ipl_rb_components *comps;
|
||||||
|
struct ipl_rl_hdr *rl_hdr;
|
||||||
|
void *buf, *ptr;
|
||||||
|
|
||||||
|
buf = vzalloc(report->size);
|
||||||
|
if (!buf)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
ptr = buf;
|
||||||
|
|
||||||
|
memcpy(ptr, report->ipib, report->ipib->hdr.len);
|
||||||
|
ipib = ptr;
|
||||||
|
if (ipl_secure_flag)
|
||||||
|
ipib->hdr.flags |= IPL_PL_FLAG_SIPL;
|
||||||
|
ipib->hdr.flags |= IPL_PL_FLAG_IPLSR;
|
||||||
|
ptr += report->ipib->hdr.len;
|
||||||
|
ptr = PTR_ALIGN(ptr, 8);
|
||||||
|
|
||||||
|
rl_hdr = ptr;
|
||||||
|
ptr += sizeof(*rl_hdr);
|
||||||
|
|
||||||
|
comps = ptr;
|
||||||
|
comps->rbt = IPL_RBT_COMPONENTS;
|
||||||
|
ptr += sizeof(*comps);
|
||||||
|
list_for_each_entry(comp, &report->components, list) {
|
||||||
|
memcpy(ptr, &comp->entry, sizeof(comp->entry));
|
||||||
|
ptr += sizeof(comp->entry);
|
||||||
|
}
|
||||||
|
comps->len = ptr - (void *)comps;
|
||||||
|
|
||||||
|
certs = ptr;
|
||||||
|
certs->rbt = IPL_RBT_CERTIFICATES;
|
||||||
|
ptr += sizeof(*certs);
|
||||||
|
list_for_each_entry(cert, &report->certificates, list) {
|
||||||
|
memcpy(ptr, &cert->entry, sizeof(cert->entry));
|
||||||
|
ptr += sizeof(cert->entry);
|
||||||
|
}
|
||||||
|
certs->len = ptr - (void *)certs;
|
||||||
|
rl_hdr->len = ptr - (void *)rl_hdr;
|
||||||
|
|
||||||
|
list_for_each_entry(cert, &report->certificates, list) {
|
||||||
|
memcpy(ptr, cert->key, cert->entry.len);
|
||||||
|
ptr += cert->entry.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
BUG_ON(ptr > buf + report->size);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipl_report_free(struct ipl_report *report)
|
||||||
|
{
|
||||||
|
struct ipl_report_component *comp, *ncomp;
|
||||||
|
struct ipl_report_certificate *cert, *ncert;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(comp, ncomp, &report->components, list)
|
||||||
|
vfree(comp);
|
||||||
|
|
||||||
|
list_for_each_entry_safe(cert, ncert, &report->certificates, list)
|
||||||
|
vfree(cert);
|
||||||
|
|
||||||
|
vfree(report);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue