diff options
Diffstat (limited to 'arch/s390/kernel/ipl.c')
-rw-r--r-- | arch/s390/kernel/ipl.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 0567de4005b4..6f2bb64cf70e 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -1705,3 +1705,137 @@ void s390_reset_system(void) | |||
1705 | __ctl_clear_bit(0, 28); | 1705 | __ctl_clear_bit(0, 28); |
1706 | diag308_reset(); | 1706 | diag308_reset(); |
1707 | } | 1707 | } |
1708 | |||
1709 | #ifdef CONFIG_KEXEC_FILE | ||
1710 | |||
1711 | int ipl_report_add_component(struct ipl_report *report, struct kexec_buf *kbuf, | ||
1712 | unsigned char flags, unsigned short cert) | ||
1713 | { | ||
1714 | struct ipl_report_component *comp; | ||
1715 | |||
1716 | comp = vzalloc(sizeof(*comp)); | ||
1717 | if (!comp) | ||
1718 | return -ENOMEM; | ||
1719 | list_add_tail(&comp->list, &report->components); | ||
1720 | |||
1721 | comp->entry.addr = kbuf->mem; | ||
1722 | comp->entry.len = kbuf->memsz; | ||
1723 | comp->entry.flags = flags; | ||
1724 | comp->entry.certificate_index = cert; | ||
1725 | |||
1726 | report->size += sizeof(comp->entry); | ||
1727 | |||
1728 | return 0; | ||
1729 | } | ||
1730 | |||
1731 | int ipl_report_add_certificate(struct ipl_report *report, void *key, | ||
1732 | unsigned long addr, unsigned long len) | ||
1733 | { | ||
1734 | struct ipl_report_certificate *cert; | ||
1735 | |||
1736 | cert = vzalloc(sizeof(*cert)); | ||
1737 | if (!cert) | ||
1738 | return -ENOMEM; | ||
1739 | list_add_tail(&cert->list, &report->certificates); | ||
1740 | |||
1741 | cert->entry.addr = addr; | ||
1742 | cert->entry.len = len; | ||
1743 | cert->key = key; | ||
1744 | |||
1745 | report->size += sizeof(cert->entry); | ||
1746 | report->size += cert->entry.len; | ||
1747 | |||
1748 | return 0; | ||
1749 | } | ||
1750 | |||
1751 | struct ipl_report *ipl_report_init(struct ipl_parameter_block *ipib) | ||
1752 | { | ||
1753 | struct ipl_report *report; | ||
1754 | |||
1755 | report = vzalloc(sizeof(*report)); | ||
1756 | if (!report) | ||
1757 | return ERR_PTR(-ENOMEM); | ||
1758 | |||
1759 | report->ipib = ipib; | ||
1760 | INIT_LIST_HEAD(&report->components); | ||
1761 | INIT_LIST_HEAD(&report->certificates); | ||
1762 | |||
1763 | report->size = ALIGN(ipib->hdr.len, 8); | ||
1764 | report->size += sizeof(struct ipl_rl_hdr); | ||
1765 | report->size += sizeof(struct ipl_rb_components); | ||
1766 | report->size += sizeof(struct ipl_rb_certificates); | ||
1767 | |||
1768 | return report; | ||
1769 | } | ||
1770 | |||
1771 | void *ipl_report_finish(struct ipl_report *report) | ||
1772 | { | ||
1773 | struct ipl_report_certificate *cert; | ||
1774 | struct ipl_report_component *comp; | ||
1775 | struct ipl_rb_certificates *certs; | ||
1776 | struct ipl_parameter_block *ipib; | ||
1777 | struct ipl_rb_components *comps; | ||
1778 | struct ipl_rl_hdr *rl_hdr; | ||
1779 | void *buf, *ptr; | ||
1780 | |||
1781 | buf = vzalloc(report->size); | ||
1782 | if (!buf) | ||
1783 | return ERR_PTR(-ENOMEM); | ||
1784 | ptr = buf; | ||
1785 | |||
1786 | memcpy(ptr, report->ipib, report->ipib->hdr.len); | ||
1787 | ipib = ptr; | ||
1788 | if (ipl_secure_flag) | ||
1789 | ipib->hdr.flags |= IPL_PL_FLAG_SIPL; | ||
1790 | ipib->hdr.flags |= IPL_PL_FLAG_IPLSR; | ||
1791 | ptr += report->ipib->hdr.len; | ||
1792 | ptr = PTR_ALIGN(ptr, 8); | ||
1793 | |||
1794 | rl_hdr = ptr; | ||
1795 | ptr += sizeof(*rl_hdr); | ||
1796 | |||
1797 | comps = ptr; | ||
1798 | comps->rbt = IPL_RBT_COMPONENTS; | ||
1799 | ptr += sizeof(*comps); | ||
1800 | list_for_each_entry(comp, &report->components, list) { | ||
1801 | memcpy(ptr, &comp->entry, sizeof(comp->entry)); | ||
1802 | ptr += sizeof(comp->entry); | ||
1803 | } | ||
1804 | comps->len = ptr - (void *)comps; | ||
1805 | |||
1806 | certs = ptr; | ||
1807 | certs->rbt = IPL_RBT_CERTIFICATES; | ||
1808 | ptr += sizeof(*certs); | ||
1809 | list_for_each_entry(cert, &report->certificates, list) { | ||
1810 | memcpy(ptr, &cert->entry, sizeof(cert->entry)); | ||
1811 | ptr += sizeof(cert->entry); | ||
1812 | } | ||
1813 | certs->len = ptr - (void *)certs; | ||
1814 | rl_hdr->len = ptr - (void *)rl_hdr; | ||
1815 | |||
1816 | list_for_each_entry(cert, &report->certificates, list) { | ||
1817 | memcpy(ptr, cert->key, cert->entry.len); | ||
1818 | ptr += cert->entry.len; | ||
1819 | } | ||
1820 | |||
1821 | BUG_ON(ptr > buf + report->size); | ||
1822 | return buf; | ||
1823 | } | ||
1824 | |||
1825 | int ipl_report_free(struct ipl_report *report) | ||
1826 | { | ||
1827 | struct ipl_report_component *comp, *ncomp; | ||
1828 | struct ipl_report_certificate *cert, *ncert; | ||
1829 | |||
1830 | list_for_each_entry_safe(comp, ncomp, &report->components, list) | ||
1831 | vfree(comp); | ||
1832 | |||
1833 | list_for_each_entry_safe(cert, ncert, &report->certificates, list) | ||
1834 | vfree(cert); | ||
1835 | |||
1836 | vfree(report); | ||
1837 | |||
1838 | return 0; | ||
1839 | } | ||
1840 | |||
1841 | #endif | ||