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 | ␊ |
15 | #ifndef DEBUG_NVRAM␊ |
16 | #define DEBUG_NVRAM 1␊ |
17 | #endif␊ |
18 | ␊ |
19 | #if DEBUG_NVRAM␊ |
20 | #define DBG(x...) verbose(x)␊ |
21 | #else␊ |
22 | #define DBG(x...) msglog(x)␊ |
23 | #endif␊ |
24 | ␊ |
25 | /*static const char const FIRMWARE_REVISION_PROP[] = "firmware-revision";␊ |
26 | static const char const FIRMWARE_ABI_PROP[] = "firmware-abi";␊ |
27 | static const char const FIRMWARE_VENDOR_PROP[] = "firmware-vendor";␊ |
28 | static const char const FIRMWARE_ABI_32_PROP_VALUE[] = "EFI32";␊ |
29 | static const char const FIRMWARE_ABI_64_PROP_VALUE[] = "EFI64";␊ |
30 | static const char const SYSTEM_ID_PROP[] = "system-id";␊ |
31 | static const char const SYSTEM_SERIAL_PROP[] = "SystemSerialNumber";␊ |
32 | static const char const SYSTEM_TYPE_PROP[] = "system-type";␊ |
33 | static const char const MODEL_PROP[] = "Model";␊ |
34 | */␊ |
35 | const char PLATFORM_UUID[] = "platform-uuid"; ␊ |
36 | //EFI_UINT32 const FIRMWARE_FEATURE_MASK = 0x000003FF;␊ |
37 | EFI_UINT32 const STATIC_ZERO = 0;␊ |
38 | ␊ |
39 | #define kBL_GLOBAL_NVRAM_GUID "8BE4DF61-93CA-11D2-AA0D-00E098032B8C"␊ |
40 | ␊ |
41 | // Check if a system supports CSM legacy mode␊ |
42 | #define kBL_APPLE_VENDOR_NVRAM_GUID "4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14"␊ |
43 | #define UUID_LEN␉16␊ |
44 | ␊ |
45 | extern EFI_GUID* getSystemID();␊ |
46 | void NVRAM_hook(void* arg1, void* arg2, void* arg3, void* arg4);␊ |
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 | //␉msglog("NVRAM is not implemented yet\n");␊ |
85 | ␉␊ |
86 | //␉return;␊ |
87 | ␉␊ |
88 | ␉msglog("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 | ␉int cnt;␊ |
96 | ␉var = malloc(sizeof(variables)+1);␊ |
97 | ␉ClearNVRAM = getValueForKey(kClearNVRAM, &buff, &cnt, &bootInfo->bootConfig);␊ |
98 | ␉if (!ClearNVRAM) {␉␉␊ |
99 | ␉␉readNVRAM(var);␊ |
100 | ␉}␊ |
101 | ␉␉␊ |
102 | ␉Node* optionsNode = DT__FindNode("/options", true);␊ |
103 | ␉ffName = malloc(sizeof(PLATFORM_UUID)+1);␊ |
104 | ␉strcpy(ffName, PLATFORM_UUID);␊ |
105 | ␉ret = getSystemID();␊ |
106 | ␉DT__AddProperty(optionsNode, ffName, UUID_LEN, (EFI_UINT32*) ret);␉␉␊ |
107 | ␉␉␊ |
108 | ␉␉// this information can be obtained from DMI Type 0␊ |
109 | ␉␉SMBByte* p = (SMBByte*)FindFirstDmiTableOfType(0, 0x18);␊ |
110 | ␉␉FirmwareFeatures = malloc(sizeof(SMBByte));␊ |
111 | ␉␉//TODO - the bufferFF must be composed from bits p[0x12] and [0x13]. Datasheet needed␊ |
112 | ␉␉*FirmwareFeatures = ((p[19] >> 1) & 1) //USB Legacy is supported␊ |
113 | ␉␉␉| ((p[18] >> 14) & 2) //Boot from CD is supported␊ |
114 | ␉␉␉| 0x14; //default for bless (GUID partition)␊ |
115 | ␉␉␊ |
116 | ␉␉sprintf(bootName, "%s:FirmwareFeatures", kBL_APPLE_VENDOR_NVRAM_GUID);␊ |
117 | ␉␉ffName = malloc(sizeof(bootName)+1);␊ |
118 | ␉␉strcpy(ffName, bootName);␊ |
119 | ␉␉DT__AddProperty(optionsNode, ffName, sizeof(uint32_t), (char *)FirmwareFeatures); //legacy support␊ |
120 | ␉␉␊ |
121 | ␉␉sprintf(bootName, "%s:FirmwareFeaturesMask", kBL_APPLE_VENDOR_NVRAM_GUID);␊ |
122 | ␉FirmwareFeaturesMask = malloc(sizeof(EFI_UINT32));␊ |
123 | ␉*FirmwareFeaturesMask = (EFI_UINT32)0x3ff;␊ |
124 | ␉␉ffmName = malloc(sizeof(bootName)+1);␊ |
125 | ␉␉strcpy(ffmName, bootName);␉␊ |
126 | ␉␉DT__AddProperty(optionsNode, ffmName, sizeof(uint32_t), (EFI_UINT32*)FirmwareFeaturesMask); ␉␊ |
127 | ␉␉␊ |
128 | ␉␉//TODO - check, validate and fill by bvr structure.␊ |
129 | ␉␉//here I am not sure what is BootOrder: node or property?␊ |
130 | ␉␉//Node* bootNode = DT__AddChild(optionsNode, kBL_GLOBAL_NVRAM_GUID ":BootOrder");␊ |
131 | ␉␉sprintf(bootName, "%s:BootOrder", kBL_GLOBAL_NVRAM_GUID);␊ |
132 | ␉␉boName = malloc(sizeof(bootName)+1);␊ |
133 | ␉␉strcpy(boName, bootName);␉␉␊ |
134 | ␉␉DT__AddProperty(optionsNode, boName, sizeof(uint32_t), (EFI_UINT32*)&STATIC_ZERO);␉␊ |
135 | ␉␉␊ |
136 | ␉␉sprintf(bootName, "%s:Boot%04hx", kBL_GLOBAL_NVRAM_GUID, bootOptionNumber);␊ |
137 | ␉␉bnName = malloc(sizeof(bootName)+1);␊ |
138 | ␉␉strcpy(bnName, bootName);␉␉␉␊ |
139 | ␉␉DT__AddProperty(optionsNode, bnName, sizeof(uint32_t), (EFI_UINT32*)&STATIC_ZERO); ␊ |
140 | ␉␉␊ |
141 | ␉␉␊ |
142 | ␉␉//can we add here boot-properties?␊ |
143 | ␉␉//␉optionsNode = DT__FindNode("chosen", true);␊ |
144 | #if 1 //NOTYET␊ |
145 | ␉␉int lbC = 0;␊ |
146 | ␉␉while(((char*)&bootInfo->bootConfig)[lbC++]);␊ |
147 | ␉␉if (lbC > sizeof(bootInfo->bootConfig)) lbC = sizeof(bootInfo->bootConfig);␊ |
148 | ␉␉DT__AddProperty(optionsNode, "boot-args", lbC, (char*)&bootInfo->bootConfig);␉␊ |
149 | #endif␊ |
150 | ␉␉//TODO - BootCamp emulation?␊ |
151 | ␉␉/*␊ |
152 | ␉␉ romNode = DT__FindNode("/rom", true);␊ |
153 | ␉␉ DT__AddProperty(romNode, "fv-main-address"... //provided by AppleSMBIOS␊ |
154 | ␉␉ DT__AddProperty(romNode, "fv-main-size"...␊ |
155 | ␉␉ "IOEFIDevicePathType" -> "MediaFirmwareVolumeFilePath"␊ |
156 | ␉␉ "Guid" -> "2B0585EB-D8B8-49A9-8B8C-E21B01AEF2B7"␊ |
157 | ␉␉ ␊ |
158 | ␉␉ */␊ |
159 | ␉␉//end Slice␊ |
160 | ␉int i,j;␊ |
161 | ␉␉for (i=0; i<32; i++) {␊ |
162 | ␉␉␉if (var[i].Name[0]) {␊ |
163 | ␉␉␉␉msglog("NVRAM get a name %s\n", var[i].Name);␊ |
164 | ␉␉␉␉if (isdigit(var[i].Name[0])) {␊ |
165 | ␉␉␉␉␉msglog(" ...it is digit...\n");␊ |
166 | ␉␉␉␉␉continue;␊ |
167 | ␉␉␉␉}␊ |
168 | ␉␉␉␉j=0; ␊ |
169 | ␉␉␉␉while (var[i].Value[j++]);␊ |
170 | ␉␉␉␉DT__AddProperty(optionsNode, var[i].Name, j,&var[i].Value);␊ |
171 | #if DEBUG_NVRAM␊ |
172 | ␉␉␉␉msglog("NVRAM add name=%s value=%s length=%d\n", var[i].Name, var[i].Value, j);␊ |
173 | #endif␊ |
174 | ␉␉␉} else {␊ |
175 | ␉␉␉␉return;␊ |
176 | ␉␉␉}␊ |
177 | ␊ |
178 | ␉␉}␊ |
179 | }␊ |
180 | ␊ |
181 | const char NVRAM_INF[] = "nvram.inf";␊ |
182 | int readNVRAM(variables* var)␊ |
183 | {␊ |
184 | ␉int fd, fsize;␊ |
185 | ␉char* nvr = 0;␊ |
186 | ␉msglog("Start NVRAM reading\n");␊ |
187 | ␉if ((fd = open(NVRAM_INF, 0)) < 0) {␊ |
188 | ␉␉msglog("[ERROR] open NVRAM failed\n");␊ |
189 | ␉␉return -1;␊ |
190 | ␉}␊ |
191 | ␉fsize = file_size(fd);␊ |
192 | ␉if (!fsize) {␊ |
193 | ␉␉msglog(" zero NVRAM file\n");␊ |
194 | ␉␉close (fd);␊ |
195 | ␉␉return -1;␊ |
196 | ␉}␊ |
197 | ␉if ((nvr = malloc(fsize)) == NULL) {␊ |
198 | ␉␉verbose("[ERROR] alloc NVRAM memory failed\n");␊ |
199 | ␉␉close (fd);␊ |
200 | ␉␉return -1;␊ |
201 | ␉}␊ |
202 | ␉if (read (fd, nvr, fsize) != fsize) {␊ |
203 | ␉␉verbose("[ERROR] read %s failed\n", NVRAM_INF);␊ |
204 | ␉␉close (fd);␊ |
205 | ␉␉return -1;␊ |
206 | ␉}␊ |
207 | ␉close (fd);␊ |
208 | ␉if ((var = malloc(fsize)) == NULL) {␊ |
209 | ␉␉verbose("[ERROR] alloc VAR memory failed\n");␊ |
210 | ␉␉return -1;␊ |
211 | ␉}␊ |
212 | ␉int i = 0;␊ |
213 | ␉bool skipGUID;␊ |
214 | ␉while (*nvr) {␊ |
215 | ␉␉int j = 0;␊ |
216 | ␉␉skipGUID = false;␊ |
217 | ␉␉while (*nvr != 9) {␊ |
218 | ␉␉␉if (*nvr == 4) {␊ |
219 | ␉␉␉␉skipGUID = true; //TODO this is GUID␊ |
220 | ␉␉␉}␊ |
221 | ␉␉␉var[i].Name[j++] = *nvr++; ␊ |
222 | ␉␉}␊ |
223 | ␉␉nvr++; //skip \09␊ |
224 | ␉␉var[i].Name[j] = 0; //end of c-string␊ |
225 | ␉␉if (skipGUID) {␊ |
226 | ␉␉␉//TODO this is GUID␊ |
227 | ␉␉␉while (*nvr++ != 0x0A) {}␊ |
228 | ␉␉␉i--;␊ |
229 | ␉␉} else {␊ |
230 | ␉␉␉␊ |
231 | ␉␉␉j = 0;␊ |
232 | ␉␉␉char c;␊ |
233 | ␉␉␉while (*nvr != 0x0A) {␊ |
234 | ␉␉␉␉c = *nvr++;␊ |
235 | ␉␉␉␉if (c == 0x25) { //TODO this is hex ␊ |
236 | ␉␉␉␉␉int k1=*nvr++;␊ |
237 | ␉␉␉␉␉if ((k1 >= 0x30) && (k1 <= 0x39)) {␊ |
238 | ␉␉␉␉␉␉k1 = k1 - 0x30;␊ |
239 | ␉␉␉␉␉}␊ |
240 | ␉␉␉␉␉if ((k1 > 0x60) && (k1 <= 0x66)) {␊ |
241 | ␉␉␉␉␉␉k1 = k1 - 0x60 + 10;␊ |
242 | ␉␉␉␉␉}␊ |
243 | ␉␉␉␉␉int k2=*nvr++;␊ |
244 | ␉␉␉␉␉if ((k2 >= 0x30) && (k2 <= 0x39)) {␊ |
245 | ␉␉␉␉␉␉k2 = k2 - 0x30;␊ |
246 | ␉␉␉␉␉}␊ |
247 | ␉␉␉␉␉if ((k2 > 0x60) && (k2 <= 0x66)) {␊ |
248 | ␉␉␉␉␉␉k2 = k2 - 0x60 + 10;␊ |
249 | ␉␉␉␉␉}␊ |
250 | ␉␉␉␉␉c = (k1 << 4) + k2;␊ |
251 | ␉␉␉␉␉break; ␊ |
252 | ␉␉␉␉}␊ |
253 | ␉␉␉␉var[i].Value[j++] = c; ␊ |
254 | ␉␉␉}␊ |
255 | ␉␉}␊ |
256 | ␉␉i++;␊ |
257 | ␉␉if (i > fsize) {␊ |
258 | ␉␉␉break;␊ |
259 | ␉␉}␊ |
260 | ␉}␊ |
261 | ␉␊ |
262 | ␉return 0;␊ |
263 | } |