OSDN Git Service

linux-pci-root: remove an unused assignment
[android-x86/external-efivar.git] / src / guid.h
1 /*
2  * libefivar - library for the manipulation of EFI variables
3  * Copyright 2012-2013 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public License as
7  * published by the Free Software Foundation; either version 2.1 of the
8  * License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #ifndef LIBEFIVAR_GUID_H
22 #define LIBEFIVAR_GUID_H 1
23
24 #include <endian.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "efivar_endian.h"
30
31 #define GUID_FORMAT "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x"
32
33 static inline int
34 real_isspace(char c)
35 {
36         char spaces[] = " \f\n\r\t\v";
37         for (int i = 0; spaces[i] != '\0'; i++)
38                 if (c == spaces[i])
39                         return 1;
40         return 0;
41 }
42
43 static inline int
44 check_sanity(const char *text, size_t len)
45 {
46         size_t sl = strlen("84be9c3e-8a32-42c0-891c-4cd3b072becc");
47
48         errno = EINVAL;
49         if (len < sl)
50                 return -1;
51         else if (len > sl && !real_isspace(text[sl]))
52                 return -1;
53
54         if (text[8] != '-' || text[13] != '-' || text[18] != '-' ||
55                         text[23] != '-')
56                 return -1;
57
58         errno = 0;
59         return 0;
60 }
61
62 static inline int
63 check_segment_sanity(const char *text, size_t len)
64 {
65         for(unsigned int i = 0; i < len; i++) {
66                 if (text[i] >= '0' && text[i] <= '9')
67                         continue;
68                 /* "| 0x20" is tolower() without having to worry about
69                  * locale concerns, since we know everything here must
70                  * be within traditional ascii space. */
71                 if ((text[i] | 0x20) >= 'a' && (text[i] | 0x20) <= 'f')
72                         continue;
73                 errno = EINVAL;
74                 return -1;
75         }
76         return 0;
77 }
78
79 static inline int UNUSED
80 text_to_guid(const char *text, efi_guid_t *guid)
81 {
82         /* these variables represent the length of the /string/ they hold,
83          * not the interpreted length of the value from them.  Mostly the
84          * names make it more obvious to verify that my bounds checking is
85          * correct. */
86         char eightbytes[9] = "";
87         char fourbytes[5] = "";
88         char twobytes[3] = "";
89         size_t textlen = strlen(text);
90         size_t guidlen = strlen("84be9c3e-8a32-42c0-891c-4cd3b072becc");
91
92         if (textlen == guidlen + 2) {
93                 if (text[0] != '{' || text[textlen - 1] != '}') {
94                         errno = EINVAL;
95                         return -1;
96                 }
97                 text++;
98                 textlen -= 2;
99         }
100
101         if (check_sanity(text, textlen) < 0)
102                 return -1;
103
104         /* 84be9c3e-8a32-42c0-891c-4cd3b072becc
105          * ^ */
106         strncpy(eightbytes, text, 8);
107         if (check_segment_sanity(eightbytes, 8) < 0)
108                 return -1;
109         guid->a = (uint32_t)strtoul(eightbytes, NULL, 16);
110         guid->a = cpu_to_le32(guid->a);
111
112         /* 84be9c3e-8a32-42c0-891c-4cd3b072becc
113          *          ^ */
114         strncpy(fourbytes, text+9, 4);
115         if (check_segment_sanity(fourbytes, 4) < 0)
116                 return -1;
117         guid->b = (uint16_t)strtoul(fourbytes, NULL, 16);
118         guid->b = cpu_to_le16(guid->b);
119
120         /* 84be9c3e-8a32-42c0-891c-4cd3b072becc
121          *               ^ */
122         strncpy(fourbytes, text+14, 4);
123         if (check_segment_sanity(fourbytes, 4) < 0)
124                 return -1;
125         guid->c = (uint16_t)strtoul(fourbytes, NULL, 16);
126         guid->c = cpu_to_le16(guid->c);
127
128         /* 84be9c3e-8a32-42c0-891c-4cd3b072becc
129          *                    ^ */
130         strncpy(fourbytes, text+19, 4);
131         if (check_segment_sanity(fourbytes, 4) < 0)
132                 return -1;
133         guid->d = (uint16_t)strtoul(fourbytes, NULL, 16);
134         guid->d = cpu_to_be16(guid->d);
135
136         /* 84be9c3e-8a32-42c0-891c-4cd3b072becc
137          *                         ^ */
138         strncpy(twobytes, text+24, 2);
139         if (check_segment_sanity(twobytes, 2) < 0)
140                 return -1;
141         guid->e[0] = (uint8_t)strtoul(twobytes, NULL, 16);
142
143         /* 84be9c3e-8a32-42c0-891c-4cd3b072becc
144          *                           ^ */
145         strncpy(twobytes, text+26, 2);
146         if (check_segment_sanity(twobytes, 2) < 0)
147                 return -1;
148         guid->e[1] = (uint8_t)strtoul(twobytes, NULL, 16);
149
150         /* 84be9c3e-8a32-42c0-891c-4cd3b072becc
151          *                             ^ */
152         strncpy(twobytes, text+28, 2);
153         if (check_segment_sanity(twobytes, 2) < 0)
154                 return -1;
155         guid->e[2] = (uint8_t)strtoul(twobytes, NULL, 16);
156
157         /* 84be9c3e-8a32-42c0-891c-4cd3b072becc
158          *                               ^ */
159         strncpy(twobytes, text+30, 2);
160         if (check_segment_sanity(twobytes, 2) < 0)
161                 return -1;
162         guid->e[3] = (uint8_t)strtoul(twobytes, NULL, 16);
163
164         /* 84be9c3e-8a32-42c0-891c-4cd3b072becc
165          *                                 ^ */
166         strncpy(twobytes, text+32, 2);
167         if (check_segment_sanity(twobytes, 2) < 0)
168                 return -1;
169         guid->e[4] = (uint8_t)strtoul(twobytes, NULL, 16);
170
171         /* 84be9c3e-8a32-42c0-891c-4cd3b072becc
172          *                                   ^ */
173         strncpy(twobytes, text+34, 2);
174         if (check_segment_sanity(twobytes, 2) < 0)
175                 return -1;
176         guid->e[5] = (uint8_t)strtoul(twobytes, NULL, 16);
177
178         return 0;
179 }
180
181 struct guidname {
182         efi_guid_t guid;
183         char symbol[256];
184         char name[256];
185 };
186
187 #endif /* LIBEFIVAR_GUID */