~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/s390/boot/ipl_report.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <linux/init.h>
  3 #include <linux/ctype.h>
  4 #include <asm/ebcdic.h>
  5 #include <asm/sclp.h>
  6 #include <asm/sections.h>
  7 #include <asm/boot_data.h>
  8 #include <asm/physmem_info.h>
  9 #include <uapi/asm/ipl.h>
 10 #include "boot.h"
 11 
 12 int __bootdata_preserved(ipl_secure_flag);
 13 
 14 unsigned long __bootdata_preserved(ipl_cert_list_addr);
 15 unsigned long __bootdata_preserved(ipl_cert_list_size);
 16 
 17 unsigned long __bootdata(early_ipl_comp_list_addr);
 18 unsigned long __bootdata(early_ipl_comp_list_size);
 19 
 20 static struct ipl_rb_certificates *certs;
 21 static struct ipl_rb_components *comps;
 22 static bool ipl_report_needs_saving;
 23 
 24 #define for_each_rb_entry(entry, rb) \
 25         for (entry = rb->entries; \
 26              (void *) entry + sizeof(*entry) <= (void *) rb + rb->len; \
 27              entry++)
 28 
 29 static unsigned long get_cert_comp_list_size(void)
 30 {
 31         struct ipl_rb_certificate_entry *cert;
 32         struct ipl_rb_component_entry *comp;
 33         size_t size;
 34 
 35         /*
 36          * Find the length for the IPL report boot data
 37          */
 38         early_ipl_comp_list_size = 0;
 39         for_each_rb_entry(comp, comps)
 40                 early_ipl_comp_list_size += sizeof(*comp);
 41         ipl_cert_list_size = 0;
 42         for_each_rb_entry(cert, certs)
 43                 ipl_cert_list_size += sizeof(unsigned int) + cert->len;
 44         return ipl_cert_list_size + early_ipl_comp_list_size;
 45 }
 46 
 47 bool ipl_report_certs_intersects(unsigned long addr, unsigned long size,
 48                                  unsigned long *intersection_start)
 49 {
 50         struct ipl_rb_certificate_entry *cert;
 51 
 52         if (!ipl_report_needs_saving)
 53                 return false;
 54 
 55         for_each_rb_entry(cert, certs) {
 56                 if (intersects(addr, size, cert->addr, cert->len)) {
 57                         *intersection_start = cert->addr;
 58                         return true;
 59                 }
 60         }
 61         return false;
 62 }
 63 
 64 static void copy_components_bootdata(void)
 65 {
 66         struct ipl_rb_component_entry *comp, *ptr;
 67 
 68         ptr = (struct ipl_rb_component_entry *) early_ipl_comp_list_addr;
 69         for_each_rb_entry(comp, comps)
 70                 memcpy(ptr++, comp, sizeof(*ptr));
 71 }
 72 
 73 static void copy_certificates_bootdata(void)
 74 {
 75         struct ipl_rb_certificate_entry *cert;
 76         void *ptr;
 77 
 78         ptr = (void *) ipl_cert_list_addr;
 79         for_each_rb_entry(cert, certs) {
 80                 *(unsigned int *) ptr = cert->len;
 81                 ptr += sizeof(unsigned int);
 82                 memcpy(ptr, (void *) cert->addr, cert->len);
 83                 ptr += cert->len;
 84         }
 85 }
 86 
 87 int read_ipl_report(void)
 88 {
 89         struct ipl_pl_hdr *pl_hdr;
 90         struct ipl_rl_hdr *rl_hdr;
 91         struct ipl_rb_hdr *rb_hdr;
 92         unsigned long tmp;
 93         void *rl_end;
 94 
 95         /*
 96          * Check if there is a IPL report by looking at the copy
 97          * of the IPL parameter information block.
 98          */
 99         if (!ipl_block_valid ||
100             !(ipl_block.hdr.flags & IPL_PL_FLAG_IPLSR))
101                 return -1;
102         ipl_secure_flag = !!(ipl_block.hdr.flags & IPL_PL_FLAG_SIPL);
103         /*
104          * There is an IPL report, to find it load the pointer to the
105          * IPL parameter information block from lowcore and skip past
106          * the IPL parameter list, then align the address to a double
107          * word boundary.
108          */
109         tmp = (unsigned long)get_lowcore()->ipl_parmblock_ptr;
110         pl_hdr = (struct ipl_pl_hdr *) tmp;
111         tmp = (tmp + pl_hdr->len + 7) & -8UL;
112         rl_hdr = (struct ipl_rl_hdr *) tmp;
113         /* Walk through the IPL report blocks in the IPL Report list */
114         certs = NULL;
115         comps = NULL;
116         rl_end = (void *) rl_hdr + rl_hdr->len;
117         rb_hdr = (void *) rl_hdr + sizeof(*rl_hdr);
118         while ((void *) rb_hdr + sizeof(*rb_hdr) < rl_end &&
119                (void *) rb_hdr + rb_hdr->len <= rl_end) {
120 
121                 switch (rb_hdr->rbt) {
122                 case IPL_RBT_CERTIFICATES:
123                         certs = (struct ipl_rb_certificates *) rb_hdr;
124                         break;
125                 case IPL_RBT_COMPONENTS:
126                         comps = (struct ipl_rb_components *) rb_hdr;
127                         break;
128                 default:
129                         break;
130                 }
131 
132                 rb_hdr = (void *) rb_hdr + rb_hdr->len;
133         }
134 
135         /*
136          * With either the component list or the certificate list
137          * missing the kernel will stay ignorant of secure IPL.
138          */
139         if (!comps || !certs) {
140                 certs = NULL;
141                 return -1;
142         }
143 
144         ipl_report_needs_saving = true;
145         physmem_reserve(RR_IPLREPORT, (unsigned long)pl_hdr,
146                         (unsigned long)rl_end - (unsigned long)pl_hdr);
147         return 0;
148 }
149 
150 void save_ipl_cert_comp_list(void)
151 {
152         unsigned long size;
153 
154         if (!ipl_report_needs_saving)
155                 return;
156 
157         size = get_cert_comp_list_size();
158         early_ipl_comp_list_addr = physmem_alloc_top_down(RR_CERT_COMP_LIST, size, sizeof(int));
159         ipl_cert_list_addr = early_ipl_comp_list_addr + early_ipl_comp_list_size;
160 
161         copy_components_bootdata();
162         copy_certificates_bootdata();
163         physmem_free(RR_IPLREPORT);
164         ipl_report_needs_saving = false;
165 }
166 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php