0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "EFI: "fmt
0009 #include <linux/module.h>
0010 #include <linux/printk.h>
0011 #include <linux/err.h>
0012 #include <linux/efi.h>
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 int __init parse_efi_signature_list(
0038 const char *source,
0039 const void *data, size_t size,
0040 efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *))
0041 {
0042 efi_element_handler_t handler;
0043 unsigned int offs = 0;
0044
0045 pr_devel("-->%s(,%zu)\n", __func__, size);
0046
0047 while (size > 0) {
0048 const efi_signature_data_t *elem;
0049 efi_signature_list_t list;
0050 size_t lsize, esize, hsize, elsize;
0051
0052 if (size < sizeof(list))
0053 return -EBADMSG;
0054
0055 memcpy(&list, data, sizeof(list));
0056 pr_devel("LIST[%04x] guid=%pUl ls=%x hs=%x ss=%x\n",
0057 offs,
0058 &list.signature_type, list.signature_list_size,
0059 list.signature_header_size, list.signature_size);
0060
0061 lsize = list.signature_list_size;
0062 hsize = list.signature_header_size;
0063 esize = list.signature_size;
0064 elsize = lsize - sizeof(list) - hsize;
0065
0066 if (lsize > size) {
0067 pr_devel("<--%s() = -EBADMSG [overrun @%x]\n",
0068 __func__, offs);
0069 return -EBADMSG;
0070 }
0071
0072 if (lsize < sizeof(list) ||
0073 lsize - sizeof(list) < hsize ||
0074 esize < sizeof(*elem) ||
0075 elsize < esize ||
0076 elsize % esize != 0) {
0077 pr_devel("- bad size combo @%x\n", offs);
0078 return -EBADMSG;
0079 }
0080
0081 handler = get_handler_for_guid(&list.signature_type);
0082 if (!handler) {
0083 data += lsize;
0084 size -= lsize;
0085 offs += lsize;
0086 continue;
0087 }
0088
0089 data += sizeof(list) + hsize;
0090 size -= sizeof(list) + hsize;
0091 offs += sizeof(list) + hsize;
0092
0093 for (; elsize > 0; elsize -= esize) {
0094 elem = data;
0095
0096 pr_devel("ELEM[%04x]\n", offs);
0097 handler(source,
0098 &elem->signature_data,
0099 esize - sizeof(*elem));
0100
0101 data += esize;
0102 size -= esize;
0103 offs += esize;
0104 }
0105 }
0106
0107 return 0;
0108 }