| 1 | /*␊ |
| 2 | * Copyright 2008 mackerintel␊ |
| 3 | */␊ |
| 4 | ␊ |
| 5 | #include "libsaio.h"␊ |
| 6 | #include "boot.h"␊ |
| 7 | #include "bootstruct.h"␊ |
| 8 | #include "acpi.h"␊ |
| 9 | #include "efi_tables.h"␊ |
| 10 | #include "fake_efi.h"␊ |
| 11 | #include "platform.h"␊ |
| 12 | #include "smbios_patcher.h"␊ |
| 13 | ␊ |
| 14 | #ifndef DEBUG_SMBIOS␊ |
| 15 | #define DEBUG_SMBIOS 0␊ |
| 16 | #endif␊ |
| 17 | ␊ |
| 18 | #if DEBUG_SMBIOS␊ |
| 19 | #define DBG(x...)␉printf(x)␊ |
| 20 | #else␊ |
| 21 | #define DBG(x...)␊ |
| 22 | #endif␊ |
| 23 | ␊ |
| 24 | typedef struct {␊ |
| 25 | const char* key;␊ |
| 26 | const char* value;␊ |
| 27 | } SMStrEntryPair;␊ |
| 28 | ␊ |
| 29 | // defaults for a MacBook␊ |
| 30 | static const SMStrEntryPair const sm_macbook_defaults[]={␊ |
| 31 | ␉{"SMbiosvendor",␉"Apple Inc."␉␉␉},␊ |
| 32 | ␉{"SMbiosversion",␉"MB41.88Z.0073.B00.0809221748"␉},␊ |
| 33 | ␉{"SMbiosdate",␉␉"04/01/2008"␉␉␉},␊ |
| 34 | ␉{"SMmanufacter",␉"Apple Inc."␉␉␉},␊ |
| 35 | ␉{"SMproductname",␉"MacBook4,1"␉␉␉},␊ |
| 36 | ␉{"SMsystemversion",␉"1.0"␉␉␉␉},␊ |
| 37 | ␉{"SMserial",␉␉"SOMESRLNMBR"␉␉␉},␊ |
| 38 | ␉{"SMfamily",␉␉"MacBook"␉␉␉},␊ |
| 39 | ␉{"SMboardmanufacter",␉"Apple Inc."␉␉␉},␊ |
| 40 | ␉{"SMboardproduct",␉"Mac-F42D89C8"␉␉␉},␊ |
| 41 | ␉{ "",""␉}␊ |
| 42 | };␊ |
| 43 | ␊ |
| 44 | // defaults for a MacBook Pro␊ |
| 45 | static const SMStrEntryPair const sm_macbookpro_defaults[]={␊ |
| 46 | ␉{"SMbiosvendor",␉"Apple Inc."␉␉␉},␊ |
| 47 | ␉{"SMbiosversion",␉"MBP41.88Z.0073.B00.0809221748"␉},␊ |
| 48 | ␉{"SMbiosdate",␉␉"04/01/2008"␉␉␉},␊ |
| 49 | ␉{"SMmanufacter",␉"Apple Inc."␉␉␉},␊ |
| 50 | ␉{"SMproductname",␉"MacBookPro4,1"␉␉␉},␊ |
| 51 | ␉{"SMsystemversion",␉"1.0"␉␉␉␉},␊ |
| 52 | ␉{"SMserial",␉␉"SOMESRLNMBR"␉␉␉},␊ |
| 53 | ␉{"SMfamily",␉␉"MacBookPro"␉␉␉},␊ |
| 54 | ␉{"SMboardmanufacter",␉"Apple Inc."␉␉␉},␊ |
| 55 | ␉{"SMboardproduct",␉"Mac-F42D89C8"␉␉␉},␊ |
| 56 | ␉{ "",""␉}␊ |
| 57 | };␊ |
| 58 | ␊ |
| 59 | // defaults for a Mac mini ␊ |
| 60 | static const SMStrEntryPair const sm_macmini_defaults[]={␊ |
| 61 | ␉{"SMbiosvendor",␉"Apple Inc."␉␉␉},␊ |
| 62 | ␉{"SMbiosversion",␉"MM21.88Z.009A.B00.0706281359"␉},␊ |
| 63 | ␉{"SMbiosdate",␉␉"04/01/2008"␉␉␉},␊ |
| 64 | ␉{"SMmanufacter",␉"Apple Inc."␉␉␉},␊ |
| 65 | ␉{"SMproductname",␉"Macmini2,1"␉␉␉},␊ |
| 66 | ␉{"SMsystemversion",␉"1.0"␉␉␉␉},␊ |
| 67 | ␉{"SMserial",␉␉"SOMESRLNMBR"␉␉␉},␊ |
| 68 | ␉{"SMfamily",␉␉"Napa Mac"␉␉␉},␊ |
| 69 | ␉{"SMboardmanufacter",␉"Apple Inc."␉␉␉},␊ |
| 70 | ␉{"SMboardproduct",␉"Mac-F4208EAA"␉␉␉},␊ |
| 71 | ␉{ "",""␉}␊ |
| 72 | };␊ |
| 73 | ␊ |
| 74 | // defaults for an iMac␊ |
| 75 | static const SMStrEntryPair const sm_imac_defaults[]={␊ |
| 76 | ␉{"SMbiosvendor",␉"Apple Inc."␉␉␉},␊ |
| 77 | ␉{"SMbiosversion",␉"IM81.88Z.00C1.B00.0802091538"␉},␊ |
| 78 | ␉{"SMbiosdate",␉␉"04/01/2008"␉␉␉},␊ |
| 79 | ␉{"SMmanufacter",␉"Apple Inc."␉␉␉},␊ |
| 80 | ␉{"SMproductname",␉"iMac8,1"␉␉␉},␉␊ |
| 81 | ␉{"SMsystemversion",␉"1.0"␉␉␉␉},␊ |
| 82 | ␉{"SMserial",␉␉"SOMESRLNMBR"␉␉␉},␊ |
| 83 | ␉{"SMfamily",␉␉"Mac"␉␉␉␉},␊ |
| 84 | ␉{"SMboardmanufacter",␉"Apple Inc."␉␉␉},␊ |
| 85 | ␉{"SMboardproduct",␉"Mac-F227BEC8"␉␉␉},␊ |
| 86 | ␉{ "",""␉}␊ |
| 87 | };␊ |
| 88 | ␊ |
| 89 | // defaults for a Mac Pro␊ |
| 90 | static const SMStrEntryPair const sm_macpro_defaults[]={␊ |
| 91 | ␉{"SMbiosvendor",␉"Apple Computer, Inc."␉␉},␊ |
| 92 | ␉{"SMbiosversion",␉"MP31.88Z.006C.B05.0802291410"␉},␊ |
| 93 | ␉{"SMbiosdate",␉␉"04/01/2008"␉␉␉},␊ |
| 94 | ␉{"SMmanufacter",␉"Apple Computer, Inc."␉␉},␊ |
| 95 | ␉{"SMproductname",␉"MacPro3,1"␉␉␉},␊ |
| 96 | ␉{"SMsystemversion",␉"1.0"␉␉␉␉},␊ |
| 97 | ␉{"SMserial",␉␉"SOMESRLNMBR"␉␉␉},␊ |
| 98 | ␉{"SMfamily",␉␉"MacPro"␉␉␉},␊ |
| 99 | ␉{"SMboardmanufacter",␉"Apple Computer, Inc."␉␉},␊ |
| 100 | ␉{"SMboardproduct",␉"Mac-F4208DC8"␉␉␉},␊ |
| 101 | ␉{ "",""␉}␊ |
| 102 | };␊ |
| 103 | ␊ |
| 104 | static const char* sm_get_defstr(const char * key, int table_num)␊ |
| 105 | {␊ |
| 106 | ␉int␉i;␊ |
| 107 | ␉const SMStrEntryPair*␉sm_defaults;␊ |
| 108 | ␊ |
| 109 | ␉if (platformCPUFeature(CPU_FEATURE_MOBILE)) {␊ |
| 110 | ␉␉if (Platform.CPU.NoCores > 1) {␊ |
| 111 | ␉␉␉sm_defaults=sm_macbookpro_defaults;␊ |
| 112 | ␉␉} else {␊ |
| 113 | ␉␉␉sm_defaults=sm_macbook_defaults;␊ |
| 114 | ␉␉}␊ |
| 115 | ␉} else {␊ |
| 116 | ␉␉switch (Platform.CPU.NoCores) {␊ |
| 117 | ␉␉case 1: sm_defaults=sm_macmini_defaults; break;␊ |
| 118 | ␉␉case 2: sm_defaults=sm_imac_defaults; break;␊ |
| 119 | ␉␉default: sm_defaults=sm_macpro_defaults; break;␊ |
| 120 | ␉␉}␊ |
| 121 | ␉}␊ |
| 122 | ␊ |
| 123 | ␉for (i=0; sm_defaults[i].key[0]; i++) {␊ |
| 124 | ␉␉if (!strcmp (sm_defaults[i].key, key)) {␊ |
| 125 | ␉␉␉return sm_defaults[i].value;␊ |
| 126 | ␉␉}␊ |
| 127 | ␉}␊ |
| 128 | ␊ |
| 129 | ␉// Shouldn't happen␊ |
| 130 | ␉printf ("Error: no default for '%s' known\n", key);␊ |
| 131 | ␉sleep (2);␊ |
| 132 | ␉return "";␊ |
| 133 | }␊ |
| 134 | ␊ |
| 135 | static int sm_get_fsb(const char *name, int table_num)␊ |
| 136 | {␊ |
| 137 | ␉return Platform.CPU.FSBFrequency/1000000;␊ |
| 138 | }␊ |
| 139 | ␊ |
| 140 | static int sm_get_cpu (const char *name, int table_num)␊ |
| 141 | {␊ |
| 142 | ␉return Platform.CPU.CPUFrequency/1000000;␊ |
| 143 | }␊ |
| 144 | ␊ |
| 145 | static int sm_get_cputype (const char *name, int table_num)␊ |
| 146 | {␊ |
| 147 | ␉if (Platform.CPU.NoCores == 1) {␊ |
| 148 | ␉␉return 0x0101; // <01 01> Intel Core Solo?␊ |
| 149 | ␉} else if (Platform.CPU.NoCores == 2) {␊ |
| 150 | ␉␉return 0x0301; // <01 03> Intel Core 2 Duo␊ |
| 151 | ␉} else if (Platform.CPU.NoCores >= 4) {␊ |
| 152 | ␉␉return 0x0501; // <01 05> Quad-Core Intel Xeon␊ |
| 153 | ␉} else {␊ |
| 154 | ␉␉return 0x0301; // Default to Core 2 Duo␊ |
| 155 | ␉}␊ |
| 156 | }␊ |
| 157 | ␊ |
| 158 | static int sm_get_memtype (const char *name, int table_num)␊ |
| 159 | {␊ |
| 160 | ␉int␉map;␊ |
| 161 | ␊ |
| 162 | ␉if (table_num < MAX_RAM_SLOTS) {␊ |
| 163 | ␉␉map = Platform.DMI.DIMM[table_num];␊ |
| 164 | ␉␉if (Platform.RAM.DIMM[map].InUse && Platform.RAM.DIMM[map].Type != 0) {␊ |
| 165 | DBG("RAM Detected Type = %d\n", Platform.RAM.DIMM[map].Type);␊ |
| 166 | return Platform.RAM.DIMM[map].Type;␊ |
| 167 | ␉␉}␊ |
| 168 | ␉}␊ |
| 169 | ␉return SMB_MEM_TYPE_DDR2;␊ |
| 170 | }␊ |
| 171 | ␊ |
| 172 | static int sm_get_memspeed (const char *name, int table_num)␊ |
| 173 | {␊ |
| 174 | ␉int␉map;␊ |
| 175 | ␊ |
| 176 | ␉if (table_num < MAX_RAM_SLOTS) {␊ |
| 177 | ␉␉map = Platform.DMI.DIMM[table_num];␊ |
| 178 | ␉␉if (Platform.RAM.DIMM[map].InUse && Platform.RAM.DIMM[map].Frequency != 0) {␊ |
| 179 | DBG("RAM Detected Freq = %d Mhz\n", Platform.RAM.DIMM[map].Frequency);␊ |
| 180 | return Platform.RAM.DIMM[map].Frequency;␊ |
| 181 | ␉␉}␊ |
| 182 | ␉}␊ |
| 183 | ␊ |
| 184 | ␉return 800;␊ |
| 185 | }␊ |
| 186 | ␊ |
| 187 | static const char *sm_get_memvendor (const char *name, int table_num)␊ |
| 188 | {␊ |
| 189 | ␉int␉map;␊ |
| 190 | ␊ |
| 191 | ␉if (table_num < MAX_RAM_SLOTS) {␊ |
| 192 | ␉␉map = Platform.DMI.DIMM[table_num];␊ |
| 193 | ␉␉if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].Vendor) > 0) {␊ |
| 194 | ␉␉␉DBG("RAM Detected Vendor[%d]='%s'\n", table_num, Platform.RAM.DIMM[map].Vendor);␊ |
| 195 | ␉␉␉return Platform.RAM.DIMM[map].Vendor;␊ |
| 196 | ␉␉}␊ |
| 197 | ␉}␊ |
| 198 | ␉return "N/A";␊ |
| 199 | }␊ |
| 200 | ␉␊ |
| 201 | static const char *sm_get_memserial (const char *name, int table_num)␊ |
| 202 | {␊ |
| 203 | ␉int␉map;␊ |
| 204 | ␊ |
| 205 | ␉if (table_num < MAX_RAM_SLOTS) {␊ |
| 206 | ␉␉map = Platform.DMI.DIMM[table_num];␊ |
| 207 | ␉␉if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].SerialNo) > 0) {␊ |
| 208 | DBG("name = %s, map=%d, RAM Detected SerialNo[%d]='%s'\n", name ? name : "", ␊ |
| 209 | map, table_num, Platform.RAM.DIMM[map].SerialNo);␊ |
| 210 | return Platform.RAM.DIMM[map].SerialNo;␊ |
| 211 | ␉␉}␊ |
| 212 | ␉}␊ |
| 213 | ␉return "N/A";␊ |
| 214 | }␊ |
| 215 | ␊ |
| 216 | static const char *sm_get_mempartno (const char *name, int table_num)␊ |
| 217 | {␊ |
| 218 | ␉int␉map;␊ |
| 219 | ␊ |
| 220 | ␉if (table_num < MAX_RAM_SLOTS) {␊ |
| 221 | ␉␉map = Platform.DMI.DIMM[table_num];␊ |
| 222 | ␉␉if (Platform.RAM.DIMM[map].InUse && strlen(Platform.RAM.DIMM[map].PartNo) > 0) {␊ |
| 223 | ␉␉␉DBG("Ram Detected PartNo[%d]='%s'\n", table_num, Platform.RAM.DIMM[map].PartNo);␊ |
| 224 | ␉␉␉return Platform.RAM.DIMM[map].PartNo;␊ |
| 225 | ␉␉}␊ |
| 226 | ␉}␊ |
| 227 | ␉return "N/A";␊ |
| 228 | }␊ |
| 229 | ␊ |
| 230 | static int sm_one (int tablen)␊ |
| 231 | {␊ |
| 232 | ␉return 1;␊ |
| 233 | }␊ |
| 234 | ␊ |
| 235 | struct smbios_property smbios_properties[]=␊ |
| 236 | {␊ |
| 237 | ␉{.name="SMbiosvendor",␉␉.table_type= 0,␉.value_type=SMSTRING,␉.offset=0x04,␉.auto_str=sm_get_defstr␉},␊ |
| 238 | ␉{.name="SMbiosversion",␉␉.table_type= 0,␉.value_type=SMSTRING,␉.offset=0x05,␉.auto_str=sm_get_defstr␉},␊ |
| 239 | ␉{.name="SMbiosdate",␉␉.table_type= 0,␉.value_type=SMSTRING,␉.offset=0x08,␉.auto_str=sm_get_defstr␉},␊ |
| 240 | ␉{.name="SMmanufacter",␉␉.table_type= 1,␉.value_type=SMSTRING,␉.offset=0x04,␉.auto_str=sm_get_defstr␉},␊ |
| 241 | ␉{.name="SMproductname",␉␉.table_type= 1,␉.value_type=SMSTRING,␉.offset=0x05,␉.auto_str=sm_get_defstr␉},␊ |
| 242 | ␉{.name="SMsystemversion",␉.table_type= 1,␉.value_type=SMSTRING,␉.offset=0x06,␉.auto_str=sm_get_defstr␉},␊ |
| 243 | ␉{.name="SMserial",␉␉.table_type= 1,␉.value_type=SMSTRING,␉.offset=0x07,␉.auto_str=sm_get_defstr␉},␊ |
| 244 | ␉{.name="SMUUID",␉␉.table_type= 1, .value_type=SMOWORD,␉.offset=0x08,␉.auto_oword=0␉␉},␊ |
| 245 | ␉{.name="SMfamily",␉␉.table_type= 1,␉.value_type=SMSTRING,␉.offset=0x1a,␉.auto_str=sm_get_defstr␉},␊ |
| 246 | ␉{.name="SMboardmanufacter",␉.table_type= 2, .value_type=SMSTRING,␉.offset=0x04,␉.auto_str=sm_get_defstr␉},␊ |
| 247 | ␉{.name="SMboardproduct",␉.table_type= 2, .value_type=SMSTRING,␉.offset=0x05,␉.auto_str=sm_get_defstr␉},␊ |
| 248 | ␉{.name="SMexternalclock",␉.table_type= 4,␉.value_type=SMWORD,␉.offset=0x12,␉.auto_int=sm_get_fsb␉},␊ |
| 249 | ␉{.name="SMmaximalclock",␉.table_type= 4,␉.value_type=SMWORD,␉.offset=0x14,␉.auto_int=sm_get_cpu␉},␊ |
| 250 | ␉{.name="SMmemdevloc",␉␉.table_type=17,␉.value_type=SMSTRING,␉.offset=0x10,␉.auto_str=0␉␉},␊ |
| 251 | ␉{.name="SMmembankloc",␉␉.table_type=17,␉.value_type=SMSTRING,␉.offset=0x11,␉.auto_str=0␉␉},␊ |
| 252 | ␉{.name="SMmemtype",␉␉.table_type=17,␉.value_type=SMBYTE,␉.offset=0x12,␉.auto_int=sm_get_memtype},␊ |
| 253 | ␉{.name="SMmemspeed",␉␉.table_type=17,␉.value_type=SMWORD,␉.offset=0x15,␉.auto_int=sm_get_memspeed},␊ |
| 254 | ␉{.name="SMmemmanufacter",␉.table_type=17,␉.value_type=SMSTRING,␉.offset=0x17,␉.auto_str=sm_get_memvendor},␊ |
| 255 | ␉{.name="SMmemserial",␉␉.table_type=17,␉.value_type=SMSTRING,␉.offset=0x18,␉.auto_str=sm_get_memserial},␊ |
| 256 | ␉{.name="SMmempart",␉␉.table_type=17,␉.value_type=SMSTRING,␉.offset=0x1A,␉.auto_str=sm_get_mempartno},␊ |
| 257 | ␉{.name="SMcputype",␉␉.table_type=131,.value_type=SMWORD,␉.offset=0x04,␉.auto_int=sm_get_cputype},␊ |
| 258 | ␉{.name="SMbusspeed",␉␉.table_type=132,.value_type=SMWORD,␉.offset=0x04,␉.auto_str=0␉␉}␊ |
| 259 | };␊ |
| 260 | ␊ |
| 261 | struct smbios_table_description smbios_table_descriptions[]=␊ |
| 262 | {␊ |
| 263 | ␉{.type=0,␉.len=0x18,␉.numfunc=sm_one},␊ |
| 264 | ␉{.type=1,␉.len=0x1b,␉.numfunc=sm_one},␊ |
| 265 | ␉{.type=2,␉.len=0x0f,␉.numfunc=sm_one},␊ |
| 266 | ␉{.type=4,␉.len=0x2a,␉.numfunc=sm_one},␊ |
| 267 | ␉{.type=17,␉.len=0x1c,␉.numfunc=0},␊ |
| 268 | ␉{.type=131,␉.len=0x06,␉.numfunc=sm_one},␊ |
| 269 | ␉{.type=132,␉.len=0x06,␉.numfunc=sm_one}␊ |
| 270 | };␊ |
| 271 | ␊ |
| 272 | // getting smbios addr with fast compare ops, late checksum testing ...␊ |
| 273 | #define COMPARE_DWORD(a,b) ( *((u_int32_t *) a) == *((u_int32_t *) b) )␊ |
| 274 | static const char * const SMTAG = "_SM_";␊ |
| 275 | static const char* const DMITAG= "_DMI_";␊ |
| 276 | ␊ |
| 277 | static struct SMBEntryPoint *getAddressOfSmbiosTable(void)␊ |
| 278 | {␊ |
| 279 | ␉struct SMBEntryPoint␉*smbios;␊ |
| 280 | ␉/* ␊ |
| 281 | ␉ * The logic is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking␊ |
| 282 | ␉ * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_").␊ |
| 283 | ␉ */␊ |
| 284 | ␉smbios = (struct SMBEntryPoint*) SMBIOS_RANGE_START;␊ |
| 285 | ␉while (smbios <= (struct SMBEntryPoint *)SMBIOS_RANGE_END) {␊ |
| 286 | if (COMPARE_DWORD(smbios->anchor, SMTAG) && ␊ |
| 287 | COMPARE_DWORD(smbios->dmi.anchor, DMITAG) &&␊ |
| 288 | smbios->dmi.anchor[4]==DMITAG[4] &&␊ |
| 289 | checksum8(smbios, sizeof(struct SMBEntryPoint)) == 0)␊ |
| 290 | ␉ {␊ |
| 291 | return smbios;␊ |
| 292 | ␉ }␊ |
| 293 | smbios = (struct SMBEntryPoint*) ( ((char*) smbios) + 16 );␊ |
| 294 | ␉}␊ |
| 295 | ␉printf("ERROR: Unable to find SMBIOS!\n");␊ |
| 296 | ␉pause();␊ |
| 297 | ␉return NULL;␊ |
| 298 | }␊ |
| 299 | ␊ |
| 300 | /** Compute necessary space requirements for new smbios */␊ |
| 301 | static struct SMBEntryPoint *smbios_dry_run(struct SMBEntryPoint *origsmbios)␊ |
| 302 | {␊ |
| 303 | ␉struct SMBEntryPoint␉*ret;␊ |
| 304 | ␉char␉␉␉*smbiostables;␊ |
| 305 | ␉char␉␉␉*tablesptr;␊ |
| 306 | ␉int␉␉␉origsmbiosnum;␊ |
| 307 | ␉int␉␉␉i, j;␊ |
| 308 | ␉int␉␉␉tablespresent[256];␊ |
| 309 | ␉bool␉␉␉do_auto=true;␊ |
| 310 | ␊ |
| 311 | ␉bzero(tablespresent, sizeof(tablespresent));␊ |
| 312 | ␊ |
| 313 | ␉getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);␊ |
| 314 | ␊ |
| 315 | ␉ret = (struct SMBEntryPoint *)AllocateKernelMemory(sizeof(struct SMBEntryPoint));␊ |
| 316 | ␉if (origsmbios) {␊ |
| 317 | ␉␉smbiostables = (char *)origsmbios->dmi.tableAddress;␊ |
| 318 | ␉␉origsmbiosnum = origsmbios->dmi.structureCount;␊ |
| 319 | ␉} else {␊ |
| 320 | ␉␉smbiostables = NULL;␊ |
| 321 | ␉␉origsmbiosnum = 0;␊ |
| 322 | ␉}␊ |
| 323 | ␊ |
| 324 | ␉// _SM_␊ |
| 325 | ␉ret->anchor[0] = 0x5f;␊ |
| 326 | ␉ret->anchor[1] = 0x53;␊ |
| 327 | ␉ret->anchor[2] = 0x4d;␊ |
| 328 | ␉ret->anchor[3] = 0x5f; ␊ |
| 329 | ␉ret->entryPointLength = sizeof(*ret);␊ |
| 330 | ␉ret->majorVersion = 2;␊ |
| 331 | ␉ret->minorVersion = 1;␊ |
| 332 | ␉ret->maxStructureSize = 0; // will be calculated later in this function␊ |
| 333 | ␉ret->entryPointRevision = 0;␊ |
| 334 | ␉for (i=0;i<5;i++) {␊ |
| 335 | ␉␉ret->formattedArea[i] = 0;␊ |
| 336 | ␉}␊ |
| 337 | ␉//_DMI_␊ |
| 338 | ␉ret->dmi.anchor[0] = 0x5f;␊ |
| 339 | ␉ret->dmi.anchor[1] = 0x44;␊ |
| 340 | ␉ret->dmi.anchor[2] = 0x4d;␊ |
| 341 | ␉ret->dmi.anchor[3] = 0x49;␊ |
| 342 | ␉ret->dmi.anchor[4] = 0x5f;␊ |
| 343 | ␉ret->dmi.tableLength = 0; // will be calculated later in this function␊ |
| 344 | ␉ret->dmi.tableAddress = 0; // will be initialized in smbios_real_run()␊ |
| 345 | ␉ret->dmi.structureCount = 0; // will be calculated later in this function␊ |
| 346 | ␉ret->dmi.bcdRevision = 0x21;␊ |
| 347 | ␉tablesptr = smbiostables;␊ |
| 348 | ␊ |
| 349 | // add stringlen of overrides to original stringlen, update maxStructure size adequately, ␊ |
| 350 | // update structure count and tablepresent[type] with count of type. ␊ |
| 351 | ␉if (smbiostables) {␊ |
| 352 | ␉␉for (i=0; i<origsmbiosnum; i++) {␊ |
| 353 | ␉␉␉struct smbios_table_header␉*cur = (struct smbios_table_header *)tablesptr;␊ |
| 354 | ␉␉␉char␉␉␉␉*stringsptr;␊ |
| 355 | ␉␉␉int␉␉␉␉stringlen;␊ |
| 356 | ␊ |
| 357 | ␉␉␉tablesptr += cur->length;␊ |
| 358 | ␉␉␉stringsptr = tablesptr;␊ |
| 359 | ␉␉␉for (; tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++);␊ |
| 360 | ␉␉␉tablesptr += 2;␊ |
| 361 | ␉␉␉stringlen = tablesptr - stringsptr - 1;␊ |
| 362 | ␉␉␉if (stringlen == 1) {␊ |
| 363 | ␉␉␉␉stringlen = 0;␊ |
| 364 | ␉␉␉}␊ |
| 365 | ␉␉␉for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {␊ |
| 366 | ␉␉␉␉const char␉*str;␊ |
| 367 | ␉␉␉␉int␉␉size;␊ |
| 368 | ␉␉␉␉char␉␉altname[40];␊ |
| 369 | ␊ |
| 370 | ␉␉␉␉sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[cur->type] + 1);␉␉␉␉␊ |
| 371 | ␉␉␉␉if (smbios_properties[j].table_type == cur->type &&␊ |
| 372 | ␉␉␉␉ smbios_properties[j].value_type == SMSTRING &&␊ |
| 373 | ␉␉␉␉ (getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig) ||␊ |
| 374 | ␉␉␉␉ getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig)))␊ |
| 375 | ␉␉␉␉{␊ |
| 376 | ␉␉␉␉␉stringlen += size + 1;␊ |
| 377 | ␉␉␉␉} else if (smbios_properties[j].table_type == cur->type &&␊ |
| 378 | ␉␉␉␉ smbios_properties[j].value_type == SMSTRING &&␊ |
| 379 | ␉␉␉␉ do_auto && smbios_properties[j].auto_str)␊ |
| 380 | ␉␉␉␉{␊ |
| 381 | ␉␉␉␉␉stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1;␊ |
| 382 | ␉␉␉␉}␊ |
| 383 | ␉␉␉}␊ |
| 384 | ␉␉␉if (stringlen == 0) {␊ |
| 385 | ␉␉␉␉stringlen = 1;␊ |
| 386 | ␉␉␉}␊ |
| 387 | ␉␉␉stringlen++;␊ |
| 388 | ␉␉␉if (ret->maxStructureSize < cur->length+stringlen) {␊ |
| 389 | ␉␉␉␉ret->maxStructureSize=cur->length+stringlen;␊ |
| 390 | ␉␉␉}␊ |
| 391 | ␉␉␉ret->dmi.tableLength += cur->length+stringlen;␊ |
| 392 | ␉␉␉ret->dmi.structureCount++;␊ |
| 393 | ␉␉␉tablespresent[cur->type]++;␊ |
| 394 | ␉␉}␊ |
| 395 | ␉}␊ |
| 396 | // Add eventually table types whose detected count would be < required count, and update ret header with:␊ |
| 397 | // new stringlen addons, structure count, and tablepresent[type] count adequately␊ |
| 398 | ␉for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {␊ |
| 399 | ␉␉int␉numnec=-1;␊ |
| 400 | ␉␉char␉buffer[40];␊ |
| 401 | ␊ |
| 402 | ␉␉sprintf(buffer, "SMtable%d", i);␊ |
| 403 | ␉␉if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {␊ |
| 404 | ␉␉␉numnec = -1;␊ |
| 405 | ␉␉}␊ |
| 406 | ␉␉if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) {␊ |
| 407 | ␉␉␉numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);␊ |
| 408 | ␉␉}␊ |
| 409 | ␉␉while (tablespresent[smbios_table_descriptions[i].type] < numnec) {␊ |
| 410 | ␉␉␉int␉stringlen = 0;␊ |
| 411 | ␉␉␉for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {␊ |
| 412 | ␉␉␉␉const char␉*str;␊ |
| 413 | ␉␉␉␉int␉␉size;␊ |
| 414 | ␉␉␉␉char␉␉altname[40];␊ |
| 415 | ␊ |
| 416 | ␉␉␉␉sprintf(altname, "%s_%d",smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type] + 1);␊ |
| 417 | ␉␉␉␉if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&␊ |
| 418 | ␉␉␉␉ smbios_properties[j].value_type == SMSTRING &&␊ |
| 419 | ␉␉␉␉ (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||␊ |
| 420 | ␉␉␉␉ getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)))␊ |
| 421 | ␉␉␉␉{␊ |
| 422 | ␉␉␉␉␉stringlen += size + 1;␊ |
| 423 | ␉␉␉␉} else if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&␊ |
| 424 | ␉␉␉␉ smbios_properties[j].value_type==SMSTRING &&␊ |
| 425 | ␉␉␉␉ do_auto && smbios_properties[j].auto_str)␊ |
| 426 | ␉␉␉␉{␊ |
| 427 | ␉␉␉␉␉stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1;␊ |
| 428 | ␉␉␉␉}␊ |
| 429 | ␉␉␉}␊ |
| 430 | ␉␉␉if (stringlen == 0) {␊ |
| 431 | ␉␉␉␉stringlen = 1;␊ |
| 432 | ␉␉␉}␊ |
| 433 | ␉␉␉stringlen++;␊ |
| 434 | ␉␉␉if (ret->maxStructureSize < smbios_table_descriptions[i].len+stringlen) {␊ |
| 435 | ␉␉␉␉ret->maxStructureSize = smbios_table_descriptions[i].len + stringlen;␊ |
| 436 | ␉␉␉}␊ |
| 437 | ␉␉␉ret->dmi.tableLength += smbios_table_descriptions[i].len + stringlen;␊ |
| 438 | ␉␉␉ret->dmi.structureCount++;␊ |
| 439 | ␉␉␉tablespresent[smbios_table_descriptions[i].type]++;␊ |
| 440 | ␉␉}␊ |
| 441 | ␉}␊ |
| 442 | ␉return ret;␊ |
| 443 | }␊ |
| 444 | ␊ |
| 445 | /** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint ␊ |
| 446 | * struct has been created by smbios_dry_run, update each table struct content of new smbios␊ |
| 447 | * int the new allocated table address of size newsmbios->tablelength.␊ |
| 448 | */␊ |
| 449 | static void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios)␊ |
| 450 | {␊ |
| 451 | ␉char *smbiostables;␊ |
| 452 | ␉char *tablesptr, *newtablesptr;␊ |
| 453 | ␉int origsmbiosnum;␊ |
| 454 | ␉// bitmask of used handles␊ |
| 455 | ␉uint8_t handles[8192]; ␊ |
| 456 | ␉uint16_t nexthandle=0;␊ |
| 457 | ␉int i, j;␊ |
| 458 | ␉int tablespresent[256];␊ |
| 459 | ␉bool do_auto=true;␊ |
| 460 | ␊ |
| 461 | extern void dumpPhysAddr(const char * title, void * a, int len);␊ |
| 462 | ␊ |
| 463 | ␉bzero(tablespresent, sizeof(tablespresent));␊ |
| 464 | ␉bzero(handles, sizeof(handles));␊ |
| 465 | ␊ |
| 466 | ␉getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig);␊ |
| 467 | ␉␊ |
| 468 | ␉newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength);␊ |
| 469 | ␉if (origsmbios) {␊ |
| 470 | ␉␉smbiostables = (char *)origsmbios->dmi.tableAddress;␊ |
| 471 | ␉␉origsmbiosnum = origsmbios->dmi.structureCount;␊ |
| 472 | ␉} else {␊ |
| 473 | ␉␉smbiostables = NULL;␊ |
| 474 | ␉␉origsmbiosnum = 0;␊ |
| 475 | ␉}␊ |
| 476 | ␉tablesptr = smbiostables;␊ |
| 477 | ␉newtablesptr = (char *)newsmbios->dmi.tableAddress;␊ |
| 478 | ␊ |
| 479 | // if old smbios exists then update new smbios with old smbios original content first␊ |
| 480 | ␉if (smbiostables) {␊ |
| 481 | ␉␉for (i=0; i<origsmbiosnum; i++) {␊ |
| 482 | ␉␉␉struct smbios_table_header␉*oldcur = (struct smbios_table_header *) tablesptr;␊ |
| 483 | ␉␉␉struct smbios_table_header␉*newcur = (struct smbios_table_header *) newtablesptr;␊ |
| 484 | ␉␉␉char␉␉␉␉*stringsptr;␊ |
| 485 | ␉␉␉int␉␉␉␉nstrings = 0;␊ |
| 486 | ␊ |
| 487 | ␉␉␉handles[(oldcur->handle) / 8] |= 1 << ((oldcur->handle) % 8);␊ |
| 488 | ␊ |
| 489 | // copy table length from old table to new table but not the old strings␊ |
| 490 | ␉␉␉memcpy(newcur,oldcur, oldcur->length);␊ |
| 491 | ␊ |
| 492 | ␉␉␉tablesptr += oldcur->length;␊ |
| 493 | ␉␉␉stringsptr = tablesptr;␊ |
| 494 | ␉␉␉newtablesptr += oldcur->length;␊ |
| 495 | ␊ |
| 496 | // calculate the number of strings in the old content␊ |
| 497 | ␉␉␉for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) {␊ |
| 498 | ␉␉␉␉if (tablesptr[0] == 0) {␊ |
| 499 | ␉␉␉␉␉nstrings++;␊ |
| 500 | ␉␉␉␉}␊ |
| 501 | ␉␉␉}␊ |
| 502 | ␉␉␉if (tablesptr != stringsptr) {␊ |
| 503 | ␉␉␉␉nstrings++;␊ |
| 504 | ␉␉␉}␊ |
| 505 | ␉␉␉tablesptr += 2;␊ |
| 506 | ␊ |
| 507 | // copy the old strings to new table␊ |
| 508 | ␉␉␉memcpy(newtablesptr, stringsptr, tablesptr-stringsptr);␊ |
| 509 | ␊ |
| 510 | ␉␉␉// point to next possible space for a string (deducting the second 0 char at the end)␊ |
| 511 | ␉␉␉newtablesptr += tablesptr - stringsptr - 1;␊ |
| 512 | if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator␊ |
| 513 | ␉␉␉␉newtablesptr--;␊ |
| 514 | ␉␉␉}␊ |
| 515 | ␊ |
| 516 | // now for each property in the table update the overrides if any (auto or user)␊ |
| 517 | ␉␉␉for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {␊ |
| 518 | ␉␉␉␉const char␉*str;␊ |
| 519 | ␉␉␉␉int␉␉size;␊ |
| 520 | ␉␉␉␉int␉␉num;␊ |
| 521 | ␉␉␉␉char␉␉altname[40];␊ |
| 522 | ␊ |
| 523 | ␉␉␉␉sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);␊ |
| 524 | ␉␉␉␉if (smbios_properties[j].table_type == newcur->type) {␊ |
| 525 | ␉␉␉␉␉switch (smbios_properties[j].value_type) {␊ |
| 526 | ␉␉␉␉␉case SMSTRING:␊ |
| 527 | ␉␉␉␉␉␉if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||␊ |
| 528 | ␉␉␉␉␉␉ getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))␊ |
| 529 | ␉␉␉␉␉␉{␊ |
| 530 | ␉␉␉␉␉␉␉memcpy(newtablesptr, str, size);␊ |
| 531 | ␉␉␉␉␉␉␉newtablesptr[size] = 0;␊ |
| 532 | ␉␉␉␉␉␉␉newtablesptr += size + 1;␊ |
| 533 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;␊ |
| 534 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_str) {␊ |
| 535 | ␉␉␉␉␉␉␉str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);␊ |
| 536 | ␉␉␉␉␉␉␉size = strlen(str);␊ |
| 537 | ␉␉␉␉␉␉␉memcpy(newtablesptr, str, size);␊ |
| 538 | ␉␉␉␉␉␉␉newtablesptr[size] = 0;␊ |
| 539 | ␉␉␉␉␉␉␉newtablesptr += size + 1;␊ |
| 540 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;␊ |
| 541 | ␉␉␉␉␉␉}␊ |
| 542 | ␉␉␉␉␉␉break;␊ |
| 543 | ␊ |
| 544 | ␉␉␉␉␉case SMOWORD:␊ |
| 545 | ␉␉␉␉␉␉if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||␊ |
| 546 | ␉␉␉␉␉␉ getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))␊ |
| 547 | ␉␉␉␉␉␉{␊ |
| 548 | ␉␉␉␉␉␉␉int␉␉k=0, t=0, kk=0;␊ |
| 549 | ␉␉␉␉␉␉␉const char␉*ptr = str;␊ |
| 550 | ␉␉␉␉␉␉␉memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);␊ |
| 551 | ␉␉␉␉␉␉␉while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {␊ |
| 552 | ␉␉␉␉␉␉␉␉ptr++;␊ |
| 553 | ␉␉␉␉␉␉␉}␊ |
| 554 | ␉␉␉␉␉␉␉if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {␊ |
| 555 | ␉␉␉␉␉␉␉␉ptr += 2;␊ |
| 556 | ␉␉␉␉␉␉␉}␊ |
| 557 | ␉␉␉␉␉␉␉for (;ptr-str<size && *ptr && k<16;ptr++) {␊ |
| 558 | ␉␉␉␉␉␉␉␉if (*ptr>='0' && *ptr<='9') {␊ |
| 559 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'0')),kk++;␊ |
| 560 | ␉␉␉␉␉␉␉␉}␊ |
| 561 | ␉␉␉␉␉␉␉␉if (*ptr>='a' && *ptr<='f') {␊ |
| 562 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'a'+10)),kk++;␊ |
| 563 | ␉␉␉␉␉␉␉␉}␊ |
| 564 | ␉␉␉␉␉␉␉␉if (*ptr>='A' && *ptr<='F') {␊ |
| 565 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'A'+10)),kk++;␊ |
| 566 | ␉␉␉␉␉␉␉␉}␊ |
| 567 | ␉␉␉␉␉␉␉␉if (kk == 2) {␊ |
| 568 | ␉␉␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;␊ |
| 569 | ␉␉␉␉␉␉␉␉␉k++;␊ |
| 570 | ␉␉␉␉␉␉␉␉␉kk = 0;␊ |
| 571 | ␉␉␉␉␉␉␉␉␉t = 0;␊ |
| 572 | ␉␉␉␉␉␉␉␉}␊ |
| 573 | ␉␉␉␉␉␉␉}␊ |
| 574 | ␉␉␉␉␉␉}␊ |
| 575 | ␉␉␉␉␉␉break;␊ |
| 576 | ␊ |
| 577 | ␉␉␉␉␉case SMBYTE:␊ |
| 578 | ␉␉␉␉␉␉if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||␊ |
| 579 | ␉␉␉␉␉␉ getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))␊ |
| 580 | ␉␉␉␉␉␉{␊ |
| 581 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;␊ |
| 582 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_int) {␊ |
| 583 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);␉␉␉␉␉␉␉␊ |
| 584 | ␉␉␉␉␉␉}␊ |
| 585 | ␉␉␉␉␉␉break;␊ |
| 586 | ␊ |
| 587 | ␉␉␉␉␉case SMWORD:␊ |
| 588 | ␉␉␉␉␉␉if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||␊ |
| 589 | ␉␉␉␉␉␉ getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))␊ |
| 590 | ␉␉␉␉␉␉{␊ |
| 591 | ␉␉␉␉␉␉␉*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;␊ |
| 592 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_int) {␊ |
| 593 | ␉␉␉␉␉␉␉*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);␊ |
| 594 | ␉␉␉␉␉␉}␊ |
| 595 | ␉␉␉␉␉␉break;␊ |
| 596 | ␉␉␉␉␉}␊ |
| 597 | ␉␉␉␉}␊ |
| 598 | ␉␉␉}␊ |
| 599 | ␉␉␉if (nstrings == 0) {␊ |
| 600 | ␉␉␉␉newtablesptr[0] = 0;␊ |
| 601 | ␉␉␉␉newtablesptr++;␊ |
| 602 | ␉␉␉}␊ |
| 603 | ␉␉␉newtablesptr[0] = 0;␊ |
| 604 | ␉␉␉newtablesptr++;␊ |
| 605 | ␉␉␉tablespresent[newcur->type]++;␊ |
| 606 | ␉␉}␊ |
| 607 | ␉}␊ |
| 608 | ␊ |
| 609 | // for each eventual complementary table not present in the original smbios, do the overrides␊ |
| 610 | ␉for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) {␊ |
| 611 | ␉␉int␉numnec = -1;␊ |
| 612 | ␉␉char␉buffer[40];␊ |
| 613 | ␊ |
| 614 | ␉␉sprintf(buffer, "SMtable%d", i);␊ |
| 615 | ␉␉if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) {␊ |
| 616 | ␉␉␉numnec = -1;␊ |
| 617 | ␉␉}␊ |
| 618 | ␉␉if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) {␊ |
| 619 | ␉␉␉numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type);␊ |
| 620 | ␉␉}␊ |
| 621 | ␉␉while (tablespresent[smbios_table_descriptions[i].type] < numnec) {␊ |
| 622 | ␉␉␉struct smbios_table_header␉*newcur = (struct smbios_table_header *) newtablesptr;␊ |
| 623 | ␉␉␉int␉␉␉␉nstrings = 0;␊ |
| 624 | ␊ |
| 625 | ␉␉␉memset(newcur,0, smbios_table_descriptions[i].len);␊ |
| 626 | ␉␉␉while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) {␊ |
| 627 | ␉␉␉␉nexthandle++;␊ |
| 628 | ␉␉␉}␊ |
| 629 | ␉␉␉newcur->handle = nexthandle;␊ |
| 630 | ␉␉␉handles[nexthandle / 8] |= 1 << (nexthandle % 8);␊ |
| 631 | ␉␉␉newcur->type = smbios_table_descriptions[i].type;␊ |
| 632 | ␉␉␉newcur->length = smbios_table_descriptions[i].len;␊ |
| 633 | ␉␉␉newtablesptr += smbios_table_descriptions[i].len;␊ |
| 634 | ␉␉␉for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) {␊ |
| 635 | ␉␉␉␉const char␉*str;␊ |
| 636 | ␉␉␉␉int␉␉size;␊ |
| 637 | ␉␉␉␉int␉␉num;␊ |
| 638 | ␉␉␉␉char␉␉altname[40];␊ |
| 639 | ␊ |
| 640 | ␉␉␉␉sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1);␊ |
| 641 | ␉␉␉␉if (smbios_properties[j].table_type == newcur->type) {␊ |
| 642 | ␉␉␉␉␉switch (smbios_properties[j].value_type) {␊ |
| 643 | ␉␉␉␉␉case SMSTRING:␊ |
| 644 | ␉␉␉␉␉␉if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||␊ |
| 645 | ␉␉␉␉␉␉ getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))␊ |
| 646 | ␉␉␉␉␉␉{␊ |
| 647 | ␉␉␉␉␉␉␉memcpy(newtablesptr, str, size);␊ |
| 648 | ␉␉␉␉␉␉␉newtablesptr[size] = 0;␊ |
| 649 | ␉␉␉␉␉␉␉newtablesptr += size + 1;␊ |
| 650 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;␊ |
| 651 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_str) {␊ |
| 652 | ␉␉␉␉␉␉␉str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);␊ |
| 653 | ␉␉␉␉␉␉␉size = strlen(str);␊ |
| 654 | ␉␉␉␉␉␉␉memcpy(newtablesptr, str, size);␊ |
| 655 | ␉␉␉␉␉␉␉newtablesptr[size] = 0;␊ |
| 656 | ␉␉␉␉␉␉␉newtablesptr += size + 1;␊ |
| 657 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings;␊ |
| 658 | ␉␉␉␉␉␉}␊ |
| 659 | ␉␉␉␉␉␉break;␊ |
| 660 | ␊ |
| 661 | ␉␉␉␉␉case SMOWORD:␊ |
| 662 | ␉␉␉␉␉␉if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) ||␊ |
| 663 | ␉␉␉␉␉␉ getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig))␊ |
| 664 | ␉␉␉␉␉␉{␊ |
| 665 | ␉␉␉␉␉␉␉int␉␉k=0, t=0, kk=0;␊ |
| 666 | ␉␉␉␉␉␉␉const char␉*ptr = str;␊ |
| 667 | ␊ |
| 668 | ␉␉␉␉␉␉␉memset(((char*)newcur) + smbios_properties[j].offset, 0, 16);␊ |
| 669 | ␉␉␉␉␉␉␉while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) {␊ |
| 670 | ␉␉␉␉␉␉␉␉ptr++;␊ |
| 671 | ␉␉␉␉␉␉␉}␊ |
| 672 | ␉␉␉␉␉␉␉if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) {␊ |
| 673 | ␉␉␉␉␉␉␉␉ptr += 2;␊ |
| 674 | ␉␉␉␉␉␉␉}␊ |
| 675 | ␉␉␉␉␉␉␉for (;ptr-str<size && *ptr && k<16;ptr++) {␊ |
| 676 | ␉␉␉␉␉␉␉␉if (*ptr>='0' && *ptr<='9') {␊ |
| 677 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'0')),kk++;␊ |
| 678 | ␉␉␉␉␉␉␉␉}␊ |
| 679 | ␉␉␉␉␉␉␉␉if (*ptr>='a' && *ptr<='f') {␊ |
| 680 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'a'+10)),kk++;␊ |
| 681 | ␉␉␉␉␉␉␉␉}␊ |
| 682 | ␉␉␉␉␉␉␉␉if (*ptr>='A' && *ptr<='F') {␊ |
| 683 | ␉␉␉␉␉␉␉␉␉(t=(t<<4)|(*ptr-'A'+10)),kk++;␊ |
| 684 | ␉␉␉␉␉␉␉␉}␊ |
| 685 | ␉␉␉␉␉␉␉␉if (kk == 2) {␊ |
| 686 | ␉␉␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t;␊ |
| 687 | ␉␉␉␉␉␉␉␉␉k++;␊ |
| 688 | ␉␉␉␉␉␉␉␉␉kk = 0;␊ |
| 689 | ␉␉␉␉␉␉␉␉␉t = 0;␊ |
| 690 | ␉␉␉␉␉␉␉␉}␊ |
| 691 | ␉␉␉␉␉␉␉}␊ |
| 692 | ␉␉␉␉␉␉}␊ |
| 693 | ␉␉␉␉␉␉break;␊ |
| 694 | ␉␉␉␉␉␉␊ |
| 695 | ␉␉␉␉␉case SMBYTE:␊ |
| 696 | ␉␉␉␉␉␉if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||␊ |
| 697 | ␉␉␉␉␉␉ getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))␊ |
| 698 | ␉␉␉␉␉␉{␊ |
| 699 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;␊ |
| 700 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_int) {␊ |
| 701 | ␉␉␉␉␉␉␉*((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);␊ |
| 702 | ␉␉␉␉␉␉}␊ |
| 703 | ␉␉␉␉␉␉break;␊ |
| 704 | ␉␉␉␉␉␉␊ |
| 705 | ␉␉␉␉␉case SMWORD:␊ |
| 706 | ␉␉␉␉␉␉if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) ||␊ |
| 707 | ␉␉␉␉␉␉ getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig))␊ |
| 708 | ␉␉␉␉␉␉{␊ |
| 709 | ␉␉␉␉␉␉␉*((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num;␊ |
| 710 | ␉␉␉␉␉␉} else if (do_auto && smbios_properties[j].auto_int) {␊ |
| 711 | ␉␉␉␉␉␉␉*((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]);␊ |
| 712 | ␉␉␉␉␉␉}␊ |
| 713 | ␉␉␉␉␉␉break;␊ |
| 714 | ␉␉␉␉␉}␊ |
| 715 | ␉␉␉␉}␊ |
| 716 | ␉␉␉}␊ |
| 717 | ␉␉␉if (nstrings == 0) {␊ |
| 718 | ␉␉␉␉newtablesptr[0] = 0;␊ |
| 719 | ␉␉␉␉newtablesptr++;␊ |
| 720 | ␉␉␉}␊ |
| 721 | ␉␉␉newtablesptr[0] = 0;␊ |
| 722 | ␉␉␉newtablesptr++;␊ |
| 723 | ␉␉␉tablespresent[smbios_table_descriptions[i].type]++;␊ |
| 724 | ␉␉}␊ |
| 725 | ␉}␊ |
| 726 | ␊ |
| 727 | // calculate new checksums␊ |
| 728 | ␉newsmbios->dmi.checksum = 0;␊ |
| 729 | ␉newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi));␊ |
| 730 | ␉newsmbios->checksum = 0;␊ |
| 731 | ␉newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios));␊ |
| 732 | ␉verbose("Patched DMI Table\n");␊ |
| 733 | }␊ |
| 734 | ␊ |
| 735 | #define MAX_DMI_TABLES 96␊ |
| 736 | typedef struct DmiNumAssocTag {␊ |
| 737 | struct DMIHeader * dmi;␊ |
| 738 | uint8_t type;␊ |
| 739 | } DmiNumAssoc;␊ |
| 740 | ␊ |
| 741 | static DmiNumAssoc DmiTablePair[MAX_DMI_TABLES];␊ |
| 742 | static int DmiTablePairCount = 0;␊ |
| 743 | static int current_pos=0;␊ |
| 744 | static bool ftTablePairInit = true;␊ |
| 745 | ␊ |
| 746 | /** ␊ |
| 747 | * Get a table structure entry from a type specification and a smbios address␊ |
| 748 | * return NULL if table is not found␊ |
| 749 | */␊ |
| 750 | static void getSmbiosTableStructure(struct SMBEntryPoint *smbios)␊ |
| 751 | {␊ |
| 752 | struct DMIHeader * dmihdr=NULL;␊ |
| 753 | SMBByte* p;␊ |
| 754 | int i;␊ |
| 755 | ␊ |
| 756 | if (ftTablePairInit && smbios!=NULL) {␊ |
| 757 | ftTablePairInit = false;␊ |
| 758 | #if DEBUG_SMBIOS␊ |
| 759 | printf(">>> SMBIOSAddr=0x%08x\n", smbios);␊ |
| 760 | printf(">>> DMI: addr=0x%08x, len=%d, count=%d\n", smbios->dmi.tableAddress, ␊ |
| 761 | smbios->dmi.tableLength, smbios->dmi.structureCount);␊ |
| 762 | #endif␊ |
| 763 | p = (SMBByte *) smbios->dmi.tableAddress;␊ |
| 764 | for (i=0; ␊ |
| 765 | i < smbios->dmi.structureCount && ␊ |
| 766 | p + 4 <= (SMBByte *)smbios->dmi.tableAddress + smbios->dmi.tableLength; ␊ |
| 767 | i++) {␊ |
| 768 | dmihdr = (struct DMIHeader *) p;␊ |
| 769 | ␊ |
| 770 | #if DEBUG_SMBIOS␊ |
| 771 | // verbose(">>>>>> DMI(%d): type=0x%02x, len=0x%d\n",i,dmihdr->type,dmihdr->length);␊ |
| 772 | #endif␊ |
| 773 | if (dmihdr->length < 4 || dmihdr->type == 127 /* EOT */) break;␊ |
| 774 | if (DmiTablePairCount < MAX_DMI_TABLES) {␊ |
| 775 | DmiTablePair[DmiTablePairCount].dmi = dmihdr;␊ |
| 776 | DmiTablePair[DmiTablePairCount].type = dmihdr->type;␊ |
| 777 | DmiTablePairCount++;␊ |
| 778 | }␊ |
| 779 | else {␊ |
| 780 | printf("DMI table entries list is full! next entries won't be stored\n");␊ |
| 781 | }␊ |
| 782 | #if DEBUG_SMBIOS␊ |
| 783 | printf("DMI header found for table type %d, length = %d\n", dmihdr->type, dmihdr->length);␊ |
| 784 | #endif␊ |
| 785 | p = p + dmihdr->length;␊ |
| 786 | while ((p - (SMBByte *)smbios->dmi.tableAddress + 1 < smbios->dmi.tableLength) && (p[0] != 0x00 || p[1] != 0x00)) {␊ |
| 787 | p++;␊ |
| 788 | ␉ }␊ |
| 789 | p += 2;␊ |
| 790 | ␉}␊ |
| 791 | ␊ |
| 792 | }␊ |
| 793 | }␊ |
| 794 | ␊ |
| 795 | /** Get original or new smbios entry point, if sucessful, the adresses are cached for next time */␊ |
| 796 | struct SMBEntryPoint *getSmbios(int which)␊ |
| 797 | {␊ |
| 798 | static struct SMBEntryPoint *orig = NULL; // cached␊ |
| 799 | static struct SMBEntryPoint *patched = NULL; // cached␊ |
| 800 | ␊ |
| 801 | // whatever we are called with orig or new flag, initialize asap both structures␊ |
| 802 | switch (which) {␊ |
| 803 | case SMBIOS_ORIGINAL:␊ |
| 804 | if (orig==NULL) {␊ |
| 805 | orig = getAddressOfSmbiosTable();␊ |
| 806 | getSmbiosTableStructure(orig); // generate tables entry list for fast table finding␊ |
| 807 | }␊ |
| 808 | return orig;␊ |
| 809 | case SMBIOS_PATCHED:␊ |
| 810 | if (orig==NULL && (orig = getAddressOfSmbiosTable())==NULL ) {␊ |
| 811 | printf("Could not find original SMBIOS !!\n");␊ |
| 812 | pause();␊ |
| 813 | } else {␊ |
| 814 | patched = smbios_dry_run(orig);␊ |
| 815 | if(patched==NULL) {␊ |
| 816 | printf("Could not create new SMBIOS !!\n");␊ |
| 817 | pause();␊ |
| 818 | }␊ |
| 819 | else {␊ |
| 820 | smbios_real_run(orig, patched);␊ |
| 821 | }␊ |
| 822 | }␊ |
| 823 | ␊ |
| 824 | return patched;␊ |
| 825 | default:␊ |
| 826 | printf("ERROR: invalid option for getSmbios() !!\n");␊ |
| 827 | break;␊ |
| 828 | }␊ |
| 829 | ␊ |
| 830 | return NULL;␊ |
| 831 | }␊ |
| 832 | ␊ |
| 833 | /** Find first original dmi Table with a particular type */␊ |
| 834 | struct DMIHeader* FindFirstDmiTableOfType(int type, int minlength)␊ |
| 835 | {␊ |
| 836 | current_pos = 0;␊ |
| 837 | ␊ |
| 838 | return FindNextDmiTableOfType(type, minlength);␊ |
| 839 | };␊ |
| 840 | ␊ |
| 841 | /** Find next original dmi Table with a particular type */␊ |
| 842 | struct DMIHeader* FindNextDmiTableOfType(int type, int minlength)␊ |
| 843 | {␊ |
| 844 | int i;␊ |
| 845 | ␊ |
| 846 | if (ftTablePairInit) getSmbios(SMBIOS_ORIGINAL);␊ |
| 847 | ␊ |
| 848 | for (i=current_pos; i < DmiTablePairCount; i++) {␊ |
| 849 | if (type == DmiTablePair[i].type && ␊ |
| 850 | DmiTablePair[i].dmi &&␊ |
| 851 | DmiTablePair[i].dmi->length >= minlength ) {␊ |
| 852 | current_pos = i+1;␊ |
| 853 | return DmiTablePair[i].dmi;␊ |
| 854 | }␊ |
| 855 | }␊ |
| 856 | return NULL; // not found␊ |
| 857 | };␊ |
| 858 | ␊ |
| 859 | |