1 | /*␊ |
2 | * Template by (c) 2009 Evan Lojewski. All rights reserved.␊ |
3 | *␊ |
4 | * NVRAM module by Slice 2010.␊ |
5 | */␊ |
6 | ␊ |
7 | #include "libsaio.h"␊ |
8 | #include "modules.h"␊ |
9 | #include "boot.h"␊ |
10 | #include "bootstruct.h"␊ |
11 | #include "pci.h"␊ |
12 | #include "efi.h"␊ |
13 | #include "smbios_getters.h"␊ |
14 | #include "xml.h"␊ |
15 | ␊ |
16 | #ifndef DEBUG_NVRAM␊ |
17 | #define DEBUG_NVRAM 0␊ |
18 | #endif␊ |
19 | ␊ |
20 | #if DEBUG_NVRAM␊ |
21 | #define DBG(x...) printf(x)␊ |
22 | #else␊ |
23 | #define DBG(x...) msglog(x)␊ |
24 | #endif␊ |
25 | ␊ |
26 | /*static const char const FIRMWARE_REVISION_PROP[] = "firmware-revision";␊ |
27 | static const char const FIRMWARE_ABI_PROP[] = "firmware-abi";␊ |
28 | static const char const FIRMWARE_VENDOR_PROP[] = "firmware-vendor";␊ |
29 | static const char const FIRMWARE_ABI_32_PROP_VALUE[] = "EFI32";␊ |
30 | static const char const FIRMWARE_ABI_64_PROP_VALUE[] = "EFI64";␊ |
31 | static const char const SYSTEM_ID_PROP[] = "system-id";␊ |
32 | static const char const SYSTEM_SERIAL_PROP[] = "SystemSerialNumber";␊ |
33 | static const char const SYSTEM_TYPE_PROP[] = "system-type";␊ |
34 | static const char const MODEL_PROP[] = "Model";␊ |
35 | */␊ |
36 | const char PLATFORM_UUID[] = "platform-uuid"; ␊ |
37 | //EFI_UINT32 const FIRMWARE_FEATURE_MASK = 0x000003FF;␊ |
38 | EFI_UINT32 const STATIC_ZERO = 0;␊ |
39 | ␊ |
40 | #define kBL_GLOBAL_NVRAM_GUID "8BE4DF61-93CA-11D2-AA0D-00E098032B8C"␊ |
41 | ␊ |
42 | // Check if a system supports CSM legacy mode␊ |
43 | #define kBL_APPLE_VENDOR_NVRAM_GUID "4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14"␊ |
44 | #define UUID_LEN␉16␊ |
45 | ␊ |
46 | //extern EFI_GUID* getSystemID();␊ |
47 | void NVRAM_start(void);␊ |
48 | ␊ |
49 | typedef struct {␊ |
50 | ␉char Name[32];␊ |
51 | ␉char Value[512];␊ |
52 | } variables;␊ |
53 | int readNVRAM(variables* v);␊ |
54 | ␊ |
55 | ␊ |
56 | void NVRAM_hook(void* arg1, void* arg2, void* arg3, void* arg4);␊ |
57 | /*␊ |
58 | void NVRAM_start_hook(void* arg1, void* arg2, void* arg3, void* arg4)␊ |
59 | {␊ |
60 | ␉msglog("NVRAM started with ExecKernel\n");␊ |
61 | ␊ |
62 | }␊ |
63 | */␊ |
64 | ␊ |
65 | void NVRAM_start()␊ |
66 | {␊ |
67 | //␉register_hook_callback("ExecKernel", &NVRAM_start_hook); ␊ |
68 | ␉//␉register_hook_callback("Kernel Start", &NVRAM_hook);␊ |
69 | ␉register_hook_callback("ModulesLoaded", &NVRAM_hook);␊ |
70 | }␊ |
71 | ␊ |
72 | void NVRAM_hook(void* arg1, void* arg2, void* arg3, void* arg4)␊ |
73 | {␊ |
74 | ␉char␉␉bootName[128];␊ |
75 | ␉variables*␉var;␊ |
76 | ␉char*␉␉ffName;␊ |
77 | ␉uint8_t *␉FirmwareFeatures;␊ |
78 | ␉EFI_UINT32*␉FirmwareFeaturesMask;␊ |
79 | ␉char*␉␉ffmName;␊ |
80 | ␉char*␉␉boName;␊ |
81 | ␉char*␉␉bnName;␊ |
82 | //␉EFI_GUID*␉ret = 0;␊ |
83 | ␉uint16_t␉bootOptionNumber = 0;␊ |
84 | ␉int i, j;␊ |
85 | ␉␊ |
86 | //␉BLESS_EFI_LOAD_OPTION* NextBoot =(BLESS_EFI_LOAD_OPTION*)gBootOrder;␊ |
87 | ␉␊ |
88 | ␉DBG("NVRAM started with ModulesLoaded\n");␊ |
89 | ␉␊ |
90 | ␉//Slice create /options node -> /fakenvram␊ |
91 | ␉// I need to use fakenvram until I know what is happen␊ |
92 | //␉bool UseNVRAM = FALSE;␊ |
93 | ␉bool ClearNVRAM = FALSE;␊ |
94 | ␉const char* buff;␊ |
95 | //␉TagPtr␉dictionary;␊ |
96 | ␉int cnt;␊ |
97 | ␉var = malloc(sizeof(variables)+1);␊ |
98 | ␉ClearNVRAM = getValueForKey("-c", &buff, &cnt, &bootInfo->bootConfig);␊ |
99 | ␉if (!ClearNVRAM) {␉␉␊ |
100 | ␉␉readNVRAM(var);␊ |
101 | ␉}␊ |
102 | ␊ |
103 | ␉for (i=0; i<32; i++) {␊ |
104 | ␉␉if (var[i].Name[0] == 0) {␊ |
105 | ␉␉␉break;␊ |
106 | ␉␉}␊ |
107 | ␉␉if (strcmp(var[i].Name, "efi-boot-device")==0) {␊ |
108 | ␉␉␉//XMLParseFile(var[i].Value, &dictionary);␊ |
109 | ␉␉␉//buff = XMLGetProperty(dictionary, "BLLastBSDName")->string;␊ |
110 | ␉␉␉verbose("Required boot device is %s\n", var[i].Value);␊ |
111 | ␉␉␉//NextBoot->FilePathListLength = 1;␊ |
112 | ␉␉␉//strcpy(NextBoot->Description, buff);␊ |
113 | ␉␉␉break;␊ |
114 | ␉␉}␊ |
115 | ␉}␊ |
116 | ␉␊ |
117 | ␉Node* optionsNode = DT__FindNode("/options", true); //"/fakenvram"␊ |
118 | ␉ffName = malloc(sizeof(PLATFORM_UUID)+1);␊ |
119 | ␉strcpy(ffName, PLATFORM_UUID);␊ |
120 | //␉ret = getSystemID();␊ |
121 | //␉DT__AddProperty(optionsNode, ffName, UUID_LEN, (EFI_UINT32*) ret);␉␉␊ |
122 | ␉␉␊ |
123 | ␉␉// this information can be obtained from DMI Type 0␊ |
124 | ␉␉SMBByte* p = (SMBByte*)FindFirstDmiTableOfType(0, 0x18);␊ |
125 | ␉␉FirmwareFeatures = malloc(sizeof(SMBByte));␊ |
126 | ␉␉//TODO - the bufferFF must be composed from bits p[0x12] and [0x13]. Datasheet needed␊ |
127 | ␉␉*FirmwareFeatures = ((p[19] >> 1) & 1) //USB Legacy is supported␊ |
128 | ␉␉␉| ((p[18] >> 14) & 2) //Boot from CD is supported␊ |
129 | ␉␉␉| 0x14; //default for bless (GUID partition)␊ |
130 | ␉␉␊ |
131 | ␉␉sprintf(bootName, "%s:FirmwareFeatures", kBL_APPLE_VENDOR_NVRAM_GUID);␊ |
132 | ␉␉ffName = malloc(sizeof(bootName)+1);␊ |
133 | ␉␉strcpy(ffName, bootName);␊ |
134 | ␉␉DT__AddProperty(optionsNode, ffName, sizeof(uint32_t), (char *)FirmwareFeatures); //legacy support␊ |
135 | ␉␉␊ |
136 | ␉␉sprintf(bootName, "%s:FirmwareFeaturesMask", kBL_APPLE_VENDOR_NVRAM_GUID);␊ |
137 | ␉FirmwareFeaturesMask = malloc(sizeof(EFI_UINT32));␊ |
138 | ␉*FirmwareFeaturesMask = (EFI_UINT32)0x3ff;␊ |
139 | ␉␉ffmName = malloc(sizeof(bootName)+1);␊ |
140 | ␉␉strcpy(ffmName, bootName);␉␊ |
141 | ␉␉DT__AddProperty(optionsNode, ffmName, sizeof(uint32_t), (EFI_UINT32*)FirmwareFeaturesMask); ␉␊ |
142 | ␉␉␊ |
143 | ␉␉//TODO - check, validate and fill by bvr structure.␊ |
144 | ␉␉//here I am not sure what is BootOrder: node or property?␊ |
145 | ␉␉//Node* bootNode = DT__AddChild(optionsNode, kBL_GLOBAL_NVRAM_GUID ":BootOrder");␊ |
146 | ␉␉sprintf(bootName, "%s:BootOrder", kBL_GLOBAL_NVRAM_GUID);␊ |
147 | ␉␉boName = malloc(sizeof(bootName)+1);␊ |
148 | ␉␉strcpy(boName, bootName);␉␉␊ |
149 | ␉␉DT__AddProperty(optionsNode, boName, sizeof(uint32_t), (EFI_UINT32*)&STATIC_ZERO);␉␊ |
150 | ␉␉␊ |
151 | ␉␉sprintf(bootName, "%s:Boot%04hx", kBL_GLOBAL_NVRAM_GUID, bootOptionNumber);␊ |
152 | ␉␉bnName = malloc(sizeof(bootName)+1);␊ |
153 | ␉␉strcpy(bnName, bootName);␉␉␉␊ |
154 | ␉␉DT__AddProperty(optionsNode, bnName, sizeof(uint32_t), (EFI_UINT32*)&STATIC_ZERO); ␊ |
155 | ␉␉␊ |
156 | ␉␉␊ |
157 | ␉␉//can we add here boot-properties?␊ |
158 | ␉␉//␉optionsNode = DT__FindNode("chosen", true);␊ |
159 | #if NOTYET␊ |
160 | ␉␉int lbC = 0;␊ |
161 | ␉␉while(((char*)&bootInfo->bootConfig)[lbC++]);␊ |
162 | ␉␉if (lbC > sizeof(bootInfo->bootConfig)) lbC = sizeof(bootInfo->bootConfig);␊ |
163 | ␉␉DT__AddProperty(optionsNode, "boot-args", lbC, (char*)&bootInfo->bootConfig);␉␊ |
164 | #endif␊ |
165 | ␉␉//TODO - BootCamp emulation?␊ |
166 | ␉␉/*␊ |
167 | ␉␉ romNode = DT__FindNode("/rom", true);␊ |
168 | ␉␉ DT__AddProperty(romNode, "fv-main-address"... //provided by AppleSMBIOS␊ |
169 | ␉␉ DT__AddProperty(romNode, "fv-main-size"...␊ |
170 | ␉␉ "IOEFIDevicePathType" -> "MediaFirmwareVolumeFilePath"␊ |
171 | ␉␉ "Guid" -> "2B0585EB-D8B8-49A9-8B8C-E21B01AEF2B7"␊ |
172 | ␉␉ ␊ |
173 | ␉␉ */␊ |
174 | ␉␉//␊ |
175 | ␊ |
176 | ␉␉for (i=0; i<32; i++) {␊ |
177 | ␉␉␉DBG("NVRAM get a name %s\n", var[i].Name);␊ |
178 | ␉␉␉if (var[i].Name[0]) {␊ |
179 | ␉␉␉␉if (isdigit(var[i].Name[0])) {␊ |
180 | ␉␉␉␉␉msglog(" ...it is digit...\n");␊ |
181 | ␉␉␉␉␉continue;␊ |
182 | ␉␉␉␉}␊ |
183 | ␉␉␉␉j=0; ␊ |
184 | ␉␉␉␉while (var[i].Value[j++]);␊ |
185 | ␉␉␉␉DT__AddProperty(optionsNode, var[i].Name, j,&var[i].Value);␊ |
186 | #if 1 //DEBUG_NVRAM␊ |
187 | ␉␉␉␉DBG("NVRAM add name=%s value=%s length=%d\n", var[i].Name, var[i].Value, j);␊ |
188 | #endif␊ |
189 | ␉␉␉} else {␊ |
190 | ␉␉␉␉break;␊ |
191 | ␉␉␉}␊ |
192 | ␊ |
193 | ␉␉}␊ |
194 | ␉//Serialization?␊ |
195 | ␉bnName[0] = bnName[1] = 0;␊ |
196 | ␉DT__AddProperty(optionsNode, bnName, sizeof(uint32_t), (EFI_UINT32*)&STATIC_ZERO);␊ |
197 | }␊ |
198 | ␊ |
199 | const char NVRAM_INF[] = "nvram.inf";␊ |
200 | int readNVRAM(variables* var)␊ |
201 | {␊ |
202 | ␉int fd, fsize;␊ |
203 | ␉char* nvr = 0;␊ |
204 | ␉DBG("Start NVRAM reading\n");␊ |
205 | ␉if ((fd = open(NVRAM_INF, 0)) < 0) {␊ |
206 | ␉␉DBG("[ERROR] open NVRAM failed\n");␊ |
207 | ␉␉return -1;␊ |
208 | ␉}␊ |
209 | ␉fsize = file_size(fd);␊ |
210 | ␉if (!fsize) {␊ |
211 | ␉␉DBG(" zero NVRAM file\n");␊ |
212 | ␉␉close (fd);␊ |
213 | ␉␉return -1;␊ |
214 | ␉}␊ |
215 | ␉if ((nvr = malloc(fsize)) == NULL) {␊ |
216 | ␉␉DBG("[ERROR] alloc NVRAM memory failed\n");␊ |
217 | ␉␉close (fd);␊ |
218 | ␉␉return -1;␊ |
219 | ␉}␊ |
220 | ␉if (read (fd, nvr, fsize) != fsize) {␊ |
221 | ␉␉DBG("[ERROR] read %s failed\n", NVRAM_INF);␊ |
222 | ␉␉close (fd);␊ |
223 | ␉␉return -1;␊ |
224 | ␉}␊ |
225 | ␉close (fd);␊ |
226 | /*␉if ((var = malloc(fsize)) == NULL) {␊ |
227 | ␉␉DBG("[ERROR] alloc VAR memory failed\n");␊ |
228 | ␉␉return -1;␊ |
229 | ␉}*/␊ |
230 | ␉int i = 0;␊ |
231 | ␉char * onvr = nvr;␊ |
232 | ␉bool skipGUID;␊ |
233 | ␉while (*nvr) {␊ |
234 | ␉␉int j = 0;␊ |
235 | ␉␉skipGUID = false;␊ |
236 | ␉␉DBG("Name[%d]:", i);␊ |
237 | ␉␉while (*nvr != 9) {␊ |
238 | //␉␉␉DBG("%c", *nvr);␊ |
239 | ␉␉␉if (*nvr == 4) {␊ |
240 | ␉␉␉␉skipGUID = true; //TODO this is GUID␊ |
241 | ␉␉␉␉nvr++;␊ |
242 | ␉␉␉} else ␊ |
243 | ␉␉␉␉var[i].Name[j++] = *nvr++; ␊ |
244 | ␉␉}␊ |
245 | ␉␉DBG("\n");␊ |
246 | ␉␉nvr++; //skip \09␊ |
247 | ␉␉var[i].Name[j] = 0; //end of c-string␊ |
248 | ␉␉if (skipGUID) {␊ |
249 | ␉␉␉//TODO this is GUID␊ |
250 | ␉␉␉DBG("skip GUID\n");␊ |
251 | ␉␉␉while (*nvr++ != 0x0A) {}␊ |
252 | ␉␉␉i--;␊ |
253 | ␉␉} else {␊ |
254 | ␉␉␉␊ |
255 | ␉␉␉j = 0;␊ |
256 | ␉␉␉unsigned char c;␊ |
257 | ␉␉␉while (*nvr != 0x0A) {␊ |
258 | ␉␉␉␉c = *nvr++;␊ |
259 | ␉␉␉␉if (c == 0x25) { //TODO this is hex ␊ |
260 | ␉␉␉␉␉int k1=*nvr++;␊ |
261 | ␉␉␉␉␉if ((k1 >= 0x30) && (k1 <= 0x39)) {␊ |
262 | ␉␉␉␉␉␉k1 = k1 - 0x30;␊ |
263 | ␉␉␉␉␉}␊ |
264 | ␉␉␉␉␉if ((k1 > 0x60) && (k1 <= 0x66)) {␊ |
265 | ␉␉␉␉␉␉k1 = k1 - 0x60 + 10;␊ |
266 | ␉␉␉␉␉}␊ |
267 | ␉␉␉␉␉int k2=*nvr++;␊ |
268 | ␉␉␉␉␉if ((k2 >= 0x30) && (k2 <= 0x39)) {␊ |
269 | ␉␉␉␉␉␉k2 = k2 - 0x30;␊ |
270 | ␉␉␉␉␉}␊ |
271 | ␉␉␉␉␉if ((k2 > 0x60) && (k2 <= 0x66)) {␊ |
272 | ␉␉␉␉␉␉k2 = k2 - 0x60 + 10;␊ |
273 | ␉␉␉␉␉}␊ |
274 | ␉␉␉␉␉c = (k1 << 4) + k2;␊ |
275 | ␉␉␉␉␉//break; ␊ |
276 | ␉␉␉␉}␊ |
277 | ␉␉␉␉var[i].Value[j++] = c; ␊ |
278 | ␉␉␉}␊ |
279 | ␉␉␉nvr++;␊ |
280 | ␉␉␉DBG("Value[%d]:", i);␊ |
281 | ␉␉␉int m;␊ |
282 | ␉␉␉for (m=0; m<j; m++) {␊ |
283 | //␉␉␉␉DBG("%02x ", var[i].Value[m]);␊ |
284 | ␉␉␉}␊ |
285 | ␉␉␉//␉DBG("Value[%d]:%s\n", i, var[i].Value);␊ |
286 | ␉␉␉DBG("\n");␊ |
287 | ␉␉}␊ |
288 | ␉␉i++;␊ |
289 | ␉␉if ((int)(nvr - onvr) > fsize) {␊ |
290 | ␉␉␉DBG("end of buffer\n");␊ |
291 | ␉␉␉break;␊ |
292 | ␉␉}␊ |
293 | ␉}␊ |
294 | ␉var[i].Name[0]=0;␊ |
295 | ␉var[i].Name[1]=0;␊ |
296 | ␊ |
297 | ␉return 0;␊ |
298 | } |