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