1 | /*␊ |
2 | * Idea and 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 0␊ |
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 | int readNVRAM(void);␊ |
49 | ␊ |
50 | typedef struct {␊ |
51 | ␉char Name[32];␊ |
52 | ␉char Value[512];␊ |
53 | } variables;␊ |
54 | variables* var;␊ |
55 | ␊ |
56 | void NVRAM_hook(void* arg1, void* arg2, void* arg3, void* arg4)␊ |
57 | {␊ |
58 | ␉char␉␉bootName[128];␊ |
59 | ␉␊ |
60 | ␉char*␉␉ffName;␊ |
61 | ␉uint8_t *␉FirmwareFeatures;␊ |
62 | ␉uint8_t *␉FirmwareFeaturesMask;␊ |
63 | ␉char*␉␉ffmName;␊ |
64 | ␉char*␉␉boName;␊ |
65 | ␉char*␉␉bnName;␊ |
66 | ␉EFI_GUID*␉ret = 0;␊ |
67 | ␉uint16_t␉bootOptionNumber = 0;␊ |
68 | ␉msglog("NVRAM is not implemented yet\n");␊ |
69 | ␉return;␊ |
70 | ␉␊ |
71 | ␉msglog("NVRAM started\n");␊ |
72 | ␉␊ |
73 | ␉//Slice create /options node -> /fakenvram␊ |
74 | ␉// I need to use fakenvram until I know what is happen␊ |
75 | //␉bool UseNVRAM = FALSE;␊ |
76 | ␉bool ClearNVRAM = FALSE;␊ |
77 | ␉const char* buff;␊ |
78 | ␉int cnt;␊ |
79 | ␉ClearNVRAM = getValueForKey(kClearNVRAM, &buff, &cnt, &bootInfo->bootConfig);␊ |
80 | ␉if (!ClearNVRAM) {␊ |
81 | ␉␉readNVRAM();␊ |
82 | ␉}␊ |
83 | ␉␉␊ |
84 | ␉Node* optionsNode = DT__FindNode("/options", true);␊ |
85 | ␉ffName = malloc(sizeof(PLATFORM_UUID)+1);␊ |
86 | ␉strcpy(ffName, PLATFORM_UUID);␊ |
87 | ␉ret = getSystemID();␊ |
88 | ␉DT__AddProperty(optionsNode, ffName, UUID_LEN, (EFI_UINT32*) ret);␉␉␊ |
89 | ␉␉␊ |
90 | ␉␉// this information can be obtained from DMI Type 0␊ |
91 | ␉␉SMBByte* p = (SMBByte*)FindFirstDmiTableOfType(0, 0x18);␊ |
92 | ␉␉FirmwareFeatures = malloc(sizeof(SMBByte));␊ |
93 | ␉␉//TODO - the bufferFF must be composed from bits p[0x12] and [0x13]. Datasheet needed␊ |
94 | ␉␉*FirmwareFeatures = ((p[19] >> 1) & 1) //USB Legacy is supported␊ |
95 | ␉␉␉| ((p[18] >> 14) & 2) //Boot from CD is supported␊ |
96 | ␉␉␉| 0x14; //default for bless (GUID partition)␊ |
97 | ␉␉␊ |
98 | ␉␉sprintf(bootName, "%s:FirmwareFeatures", kBL_APPLE_VENDOR_NVRAM_GUID);␊ |
99 | ␉␉ffName = malloc(sizeof(bootName)+1);␊ |
100 | ␉␉strcpy(ffName, bootName);␊ |
101 | ␉␉DT__AddProperty(optionsNode, ffName, sizeof(uint32_t), (char *)FirmwareFeatures); //legacy support␊ |
102 | ␉␉␊ |
103 | ␉␉sprintf(bootName, "%s:FirmwareFeaturesMask", kBL_APPLE_VENDOR_NVRAM_GUID);␊ |
104 | ␉FirmwareFeaturesMask = malloc(sizeof(EFI_UINT32));␊ |
105 | ␉*FirmwareFeaturesMask = (EFI_UINT32)0x3ff;␊ |
106 | ␉␉ffmName = malloc(sizeof(bootName)+1);␊ |
107 | ␉␉strcpy(ffmName, bootName);␉␊ |
108 | ␉␉DT__AddProperty(optionsNode, ffmName, sizeof(uint32_t), (EFI_UINT32*)FirmwareFeaturesMask); ␉␊ |
109 | ␉␉␊ |
110 | ␉␉//TODO - check, validate and fill by bvr structure.␊ |
111 | ␉␉//here I am not sure what is BootOrder: node or property?␊ |
112 | ␉␉//Node* bootNode = DT__AddChild(optionsNode, kBL_GLOBAL_NVRAM_GUID ":BootOrder");␊ |
113 | ␉␉sprintf(bootName, "%s:BootOrder", kBL_GLOBAL_NVRAM_GUID);␊ |
114 | ␉␉boName = malloc(sizeof(bootName)+1);␊ |
115 | ␉␉strcpy(boName, bootName);␉␉␊ |
116 | ␉␉DT__AddProperty(optionsNode, boName, sizeof(uint32_t), (EFI_UINT32*)&STATIC_ZERO);␉␊ |
117 | ␉␉␊ |
118 | ␉␉sprintf(bootName, "%s:Boot%04hx", kBL_GLOBAL_NVRAM_GUID, bootOptionNumber);␊ |
119 | ␉␉bnName = malloc(sizeof(bootName)+1);␊ |
120 | ␉␉strcpy(bnName, bootName);␉␉␉␊ |
121 | ␉␉DT__AddProperty(optionsNode, bnName, sizeof(uint32_t), (EFI_UINT32*)&STATIC_ZERO); ␊ |
122 | ␉␉␊ |
123 | ␉␉␊ |
124 | ␉␉//can we add here boot-properties?␊ |
125 | ␉␉//␉optionsNode = DT__FindNode("chosen", true);␊ |
126 | #if 1 //NOTYET␊ |
127 | ␉␉int lbC = 0;␊ |
128 | ␉␉while(((char*)&bootInfo->bootConfig)[lbC++]);␊ |
129 | ␉␉if (lbC > sizeof(bootInfo->bootConfig)) lbC = sizeof(bootInfo->bootConfig);␊ |
130 | ␉␉DT__AddProperty(optionsNode, "boot-args", lbC, (char*)&bootInfo->bootConfig);␉␊ |
131 | #endif␊ |
132 | ␉␉//TODO - BootCamp emulation?␊ |
133 | ␉␉/*␊ |
134 | ␉␉ romNode = DT__FindNode("/rom", true);␊ |
135 | ␉␉ DT__AddProperty(romNode, "fv-main-address"... //provided by AppleSMBIOS␊ |
136 | ␉␉ DT__AddProperty(romNode, "fv-main-size"...␊ |
137 | ␉␉ "IOEFIDevicePathType" -> "MediaFirmwareVolumeFilePath"␊ |
138 | ␉␉ "Guid" -> "2B0585EB-D8B8-49A9-8B8C-E21B01AEF2B7"␊ |
139 | ␉␉ ␊ |
140 | ␉␉ */␊ |
141 | ␉␉//end Slice␊ |
142 | }␊ |
143 | ␊ |
144 | void NVRAM_start()␊ |
145 | {␊ |
146 | ␉register_hook_callback("Kernel Start", &NVRAM_hook);␊ |
147 | }␊ |
148 | ␊ |
149 | const char NVRAM_INF[] = "nvram.inf";␊ |
150 | int readNVRAM()␊ |
151 | {␊ |
152 | ␉int fd, fsize;␊ |
153 | ␉char* nvr = 0;␊ |
154 | ␉if ((fd = open(NVRAM_INF, 0)) < 0) {␊ |
155 | ␉␉return -1;␊ |
156 | ␉}␊ |
157 | ␉fsize = file_size(fd);␊ |
158 | ␉if ((nvr = malloc(fsize)) == NULL) {␊ |
159 | ␉␉verbose("[ERROR] alloc NVRAM memory failed\n");␊ |
160 | ␉␉close (fd);␊ |
161 | ␉␉return -1;␊ |
162 | ␉}␊ |
163 | ␉if (read (fd, nvr, fsize) != fsize) {␊ |
164 | ␉␉verbose("[ERROR] read %s failed\n", NVRAM_INF);␊ |
165 | ␉␉close (fd);␊ |
166 | ␉␉return -1;␊ |
167 | ␉}␊ |
168 | ␉close (fd);␊ |
169 | ␉if ((var = malloc(fsize)) == NULL) {␊ |
170 | ␉␉verbose("[ERROR] alloc VAR memory failed\n");␊ |
171 | ␉␉return -1;␊ |
172 | ␉}␊ |
173 | ␉int i = 0;␊ |
174 | ␉bool skipGUID;␊ |
175 | ␉while (*nvr) {␊ |
176 | ␉␉int j = 0;␊ |
177 | ␉␉skipGUID = false;␊ |
178 | ␉␉while (*nvr != 9) {␊ |
179 | ␉␉␉if (*nvr == 4) {␊ |
180 | ␉␉␉␉skipGUID = true; //TODO this is GUID␊ |
181 | ␉␉␉}␊ |
182 | ␉␉␉var[i].Name[j++] = *nvr++; ␊ |
183 | ␉␉}␊ |
184 | ␉␉nvr++; //skip \09␊ |
185 | ␉␉var[i].Name[j] = 0; //end of c-string␊ |
186 | ␉␉if (skipGUID) {␊ |
187 | ␉␉␉//TODO this is GUID␊ |
188 | ␉␉␉while (*nvr++ != 0x0A) {}␊ |
189 | ␉␉␉i--;␊ |
190 | ␉␉} else {␊ |
191 | ␉␉␉␊ |
192 | ␉␉␉j = 0;␊ |
193 | ␉␉␉char c;␊ |
194 | ␉␉␉while (*nvr != 0x0A) {␊ |
195 | ␉␉␉␉c = *nvr++;␊ |
196 | ␉␉␉␉if (c == 0x25) { //TODO this is hex ␊ |
197 | ␉␉␉␉␉int k1=*nvr++;␊ |
198 | ␉␉␉␉␉if ((k1 > 0x30) && (k1 < 0x39)) {␊ |
199 | ␉␉␉␉␉␉k1 = k1 - 0x30;␊ |
200 | ␉␉␉␉␉}␊ |
201 | ␉␉␉␉␉if ((k1 > 0x60) && (k1 < 0x69)) {␊ |
202 | ␉␉␉␉␉␉k1 = k1 - 0x60 + 10;␊ |
203 | ␉␉␉␉␉}␊ |
204 | ␉␉␉␉␉int k2=*nvr++;␊ |
205 | ␉␉␉␉␉if ((k2 > 0x30) && (k2 < 0x39)) {␊ |
206 | ␉␉␉␉␉␉k2 = k2 - 0x30;␊ |
207 | ␉␉␉␉␉}␊ |
208 | ␉␉␉␉␉if ((k2 > 0x60) && (k2 < 0x69)) {␊ |
209 | ␉␉␉␉␉␉k2 = k2 - 0x60 + 10;␊ |
210 | ␉␉␉␉␉}␊ |
211 | ␉␉␉␉␉c = (k1 << 4) + k2;␊ |
212 | ␉␉␉␉␉break; ␊ |
213 | ␉␉␉␉}␊ |
214 | ␉␉␉␉var[i].Value[j++] = c; ␊ |
215 | ␉␉␉}␊ |
216 | ␉␉}␊ |
217 | ␉␉i++;␊ |
218 | ␉␉if (i > fsize) {␊ |
219 | ␉␉␉break;␊ |
220 | ␉␉}␊ |
221 | ␉}␊ |
222 | ␉␊ |
223 | ␉return 0;␊ |
224 | } |