/* Gets the ACPI 2.0 RSDP address */ static struct acpi_2_rsdp* getAddressOfAcpi20Table() { /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */ void *acpi_addr = (void*)ACPI_RANGE_START; for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16) { if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE) { uint8_t csum = checksum8(acpi_addr, 20); /* Only assume this is a 2.0 or better table if the revision is greater than 0 * NOTE: ACPI 3.0 spec only seems to say that 1.0 tables have revision 1 * and that the current revision is 2.. I am going to assume that rev > 0 is 2.0. */ if(csum == 0 && (((struct acpi_2_rsdp*)acpi_addr)->Revision > 0)) { uint8_t csum2 = checksum8(acpi_addr, sizeof(struct acpi_2_rsdp)); if(csum2 == 0) return acpi_addr; } } } return NULL; }
static inline struct SMBEntryPoint * getAddressOfSmbiosTable() { /* First see if we can even find the damn SMBIOS table * The logic here is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_"). */ void *smbios_addr = (void*)SMBIOS_RANGE_START; for(; (smbios_addr <= (void*)SMBIOS_RANGE_END) && (*(uint32_t*)smbios_addr != SMBIOS_ANCHOR_UINT32_LE); smbios_addr += 16) ; if(smbios_addr <= (void*)SMBIOS_RANGE_END) { /* NOTE: The specification does not specifically state what to do in the event of finding an * SMBIOS anchor on an invalid table. It might be better to move this code into the for loop * so that searching can continue. */ uint8_t csum = checksum8(smbios_addr, sizeof(struct SMBEntryPoint)); /* The table already contains the checksum so we merely need to see if its checksum is now zero. */ if(csum != 0) { printf("Found SMBIOS anchor but bad table checksum. Assuming no SMBIOS.\n"); sleep(5); smbios_addr = 0; } } else { /* If this happens, it's possible that a PnP BIOS call can be done to retrieve the address of the table. * The latest versions of the spec state that modern programs should not even attempt to do this. */ printf("Unable to find SMBIOS table.\n"); sleep(5); smbios_addr = 0; } return smbios_addr; }
int birom16_write(struct birom16_state *state, uint16_t address, uint8_t *data, uint16_t size) { uint8_t buffer[4096]; memset(buffer, 0x00, sizeof(buffer)); serial_purge(state->serial); buffer[0] = BIROM16_CMD_WRITE; buffer[1] = (address & 0xFF00) >> 8; buffer[2] = (address & 0x00FF); buffer[3] = (size & 0xFF00) >> 8; buffer[4] = (size & 0x00FF); memcpy(buffer + 5, data, size); size += 5; uint8_t csum = checksum8(buffer, size); buffer[size++] = csum; LOGD("Writing %d bytes to address 0x%04X...", size, address); int rc = serial_write(state->serial, buffer, size); if (rc < size) { LOGE("Error writing to MCU."); return E_WRITE; } //Give MCU some breathing space. serial_drain(state->serial); //Expect single byte result of operation from MCU. uint8_t code = 0; uint8_t value = 0; double timeout = get_ticks() + 2; while (get_ticks() < timeout) { msleep(10); rc = serial_read(state->serial, &code, 1); if (rc < 0) { LOGE("Error reading from '%s'.", state->serial->address); return E_READ; } if (rc > 0) { if (code == BIROM16_RESP_ACK) { return E_NONE; } } } LOGE("Invalid MCU response: Code %d, value %d.", code, value); return E_MSGMALFORMED; //return E_NONE; }
/* Gets the ACPI 1.0 RSDP address */ static struct acpi_2_rsdp* getAddressOfAcpiTable() { /* TODO: Before searching the BIOS space we are supposed to search the first 1K of the EBDA */ void *acpi_addr = (void*)ACPI_RANGE_START; for(; acpi_addr <= (void*)ACPI_RANGE_END; acpi_addr += 16) { if(*(uint64_t *)acpi_addr == ACPI_SIGNATURE_UINT64_LE) { uint8_t csum = checksum8(acpi_addr, 20); if(csum == 0) { // Only return the table if it is a true version 1.0 table (Revision 0) if(((struct acpi_2_rsdp*)acpi_addr)->Revision == 0) return acpi_addr; } } } return NULL; }
SMBEntryPoint *getAddressOfSmbiosTable(void) { SMBEntryPoint *smbios; /* * The logic is to start at 0xf0000 and end at 0xfffff iterating 16 bytes at a time looking * for the SMBIOS entry-point structure anchor (literal ASCII "_SM_"). */ smbios = (SMBEntryPoint*)SMBIOS_RANGE_START; while (smbios <= (SMBEntryPoint *)SMBIOS_RANGE_END) { if (COMPARE_DWORD(smbios->anchor, SMTAG) && COMPARE_DWORD(smbios->dmi.anchor, DMITAG) && smbios->dmi.anchor[4] == DMITAG[4] && checksum8(smbios, sizeof(SMBEntryPoint)) == 0) { return smbios; } smbios = (SMBEntryPoint*)(((char*)smbios) + 16); } DBG("ERROR: Unable to find SMBIOS!\n"); pause(); return NULL; }
void smbios_real_run (struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios) { char *smbiostables=0; char *tablesptr, *newtablesptr; int origsmbiosnum=0; // bitmask of used handles uint8_t handles[8192]; uint16_t nexthandle=0; int i, j; int tablespresent[256]; BOOL do_auto=1; getBoolForKey("SMBIOSdefaults",&do_auto,&bootInfo->bootConfig); for (i=0;i<256;i++) tablespresent[i]=0; memset (handles,0,8192); newsmbios->dmi.tableAddress=(uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength); if (origsmbios) { smbiostables=(char *) origsmbios->dmi.tableAddress; origsmbiosnum=origsmbios->dmi.structureCount; } tablesptr=smbiostables; newtablesptr=(char *) newsmbios->dmi.tableAddress; if (smbiostables) for (i=0;i<origsmbiosnum;i++) { struct smbios_table_header *oldcur =(struct smbios_table_header *) tablesptr, *newcur=(struct smbios_table_header *) newtablesptr; char *stringsptr; int nstrings=0; handles[(oldcur->handle)/8]|=1<<((oldcur->handle)%8); memcpy (newcur,oldcur, oldcur->length); tablesptr+=oldcur->length; stringsptr=tablesptr; newtablesptr+=oldcur->length; for (;tablesptr[0]!=0 || tablesptr[1]!=0;tablesptr++) if (tablesptr[0]==0) nstrings++; if (tablesptr!=stringsptr) nstrings++; tablesptr+=2; memcpy (newtablesptr,stringsptr,tablesptr-stringsptr); //point to next possible space for a string newtablesptr+=tablesptr-stringsptr-1; if (nstrings==0) newtablesptr--; for (j=0;j<sizeof (smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; int num; char altname[40]; sprintf (altname, "%s_%d",smbios_properties[j].name, tablespresent[newcur->type]+1); if (smbios_properties[j].table_type==newcur->type) switch (smbios_properties[j].value_type) { case SMSTRING: if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig) ||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig)) { memcpy (newtablesptr, str,size); newtablesptr[size]=0; newtablesptr+=size+1; *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings; } else if (do_auto && smbios_properties[j].auto_str) { str=smbios_properties[j].auto_str(smbios_properties[j].name,tablespresent[newcur->type]); size=strlen (str); memcpy (newtablesptr, str,size); newtablesptr[size]=0; newtablesptr+=size+1; *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings; } break; case SMOWORD: if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig) ||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig)) { int k=0, t=0, kk=0; const char *ptr=str; memset(((char*)newcur)+smbios_properties[j].offset, 0, 16); while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) ptr++; if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) ptr+=2; for (;ptr-str<size && *ptr && k<16;ptr++) { if (*ptr>='0' && *ptr<='9') (t=(t<<4)|(*ptr-'0')),kk++; if (*ptr>='a' && *ptr<='f') (t=(t<<4)|(*ptr-'a'+10)),kk++; if (*ptr>='A' && *ptr<='F') (t=(t<<4)|(*ptr-'A'+10)),kk++; if (kk==2) { *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset+k))=t; k++; kk=0; t=0; } } } break; case SMBYTE: if (getIntForKey(altname,&num,&bootInfo->smbiosConfig) ||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig)) *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=num; else if (do_auto && smbios_properties[j].auto_int) *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset)) =smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); break; case SMWORD: if (getIntForKey(altname,&num,&bootInfo->smbiosConfig) ||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig)) *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset))=num; else if (do_auto && smbios_properties[j].auto_int) *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) =smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); break; } } if (nstrings==0) { newtablesptr[0]=0; newtablesptr++; } newtablesptr[0]=0; newtablesptr++; tablespresent[newcur->type]++; } for (i=0;i<sizeof (smbios_table_descriptions) /sizeof(smbios_table_descriptions[0]);i++) { int numnec=-1; char buffer[40]; sprintf (buffer, "SMtable%d", i); if (!getIntForKey(buffer,&numnec,&bootInfo->smbiosConfig)) numnec=-1; if (numnec==-1 && do_auto && smbios_table_descriptions[i].numfunc) numnec=smbios_table_descriptions[i].numfunc (smbios_table_descriptions[i].type); while (tablespresent[smbios_table_descriptions[i].type]<numnec) { struct smbios_table_header *newcur=(struct smbios_table_header *) newtablesptr; int nstrings=0; memset (newcur,0, smbios_table_descriptions[i].len); while (handles[(nexthandle)/8]&(1<<((nexthandle)%8))) nexthandle++; newcur->handle=nexthandle; handles[nexthandle/8]|=1<<(nexthandle%8); newcur->type=smbios_table_descriptions[i].type; newcur->length=smbios_table_descriptions[i].len; newtablesptr+=smbios_table_descriptions[i].len; for (j=0;j<sizeof (smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; int num; char altname[40]; sprintf (altname, "%s_%d",smbios_properties[j].name, tablespresent[newcur->type]+1); if (smbios_properties[j].table_type==newcur->type) switch (smbios_properties[j].value_type) { case SMSTRING: if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig) ||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig)) { memcpy (newtablesptr, str,size); newtablesptr[size]=0; newtablesptr+=size+1; *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings; } else if (do_auto && smbios_properties[j].auto_str) { str=smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]); size=strlen (str); memcpy (newtablesptr, str,size); newtablesptr[size]=0; newtablesptr+=size+1; *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=++nstrings; } break; case SMOWORD: if (getValueForKey(altname,&str, &size, &bootInfo->smbiosConfig) ||getValueForKey(smbios_properties[j].name,&str, &size, &bootInfo->smbiosConfig)) { int k=0, t=0, kk=0; const char *ptr=str; memset(((char*)newcur)+smbios_properties[j].offset, 0, 16); while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) ptr++; if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) ptr+=2; for (;ptr-str<size && *ptr && k<16;ptr++) { if (*ptr>='0' && *ptr<='9') (t=(t<<4)|(*ptr-'0')),kk++; if (*ptr>='a' && *ptr<='f') (t=(t<<4)|(*ptr-'a'+10)),kk++; if (*ptr>='A' && *ptr<='F') (t=(t<<4)|(*ptr-'A'+10)),kk++; if (kk==2) { *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset+k))=t; k++; kk=0; t=0; } } } break; case SMBYTE: if (getIntForKey(altname,&num,&bootInfo->smbiosConfig) ||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig)) *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset))=num; else if (do_auto && smbios_properties[j].auto_int) *((uint8_t*)(((char*)newcur)+smbios_properties[j].offset)) =smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); break; case SMWORD: if (getIntForKey(altname,&num,&bootInfo->smbiosConfig) ||getIntForKey(smbios_properties[j].name,&num,&bootInfo->smbiosConfig)) *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset))=num; else if (do_auto && smbios_properties[j].auto_int) *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) =smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); break; } } if (nstrings==0) { newtablesptr[0]=0; newtablesptr++; } newtablesptr[0]=0; newtablesptr++; tablespresent[smbios_table_descriptions[i].type]++; } } newsmbios->dmi.checksum=0; newsmbios->dmi.checksum=256-checksum8 (&newsmbios->dmi,sizeof (newsmbios->dmi)); newsmbios->checksum=0; newsmbios->checksum=256-checksum8 (newsmbios,sizeof (*newsmbios)); verbose("Patched DMI Table.\n"); }
/** From the origsmbios detected by getAddressOfSmbiosTable() to newsmbios whose entrypoint * struct has been created by smbios_dry_run, update each table struct content of new smbios * int the new allocated table address of size newsmbios->tablelength. */ static void smbios_real_run(struct SMBEntryPoint * origsmbios, struct SMBEntryPoint * newsmbios) { char *smbiostables; char *tablesptr, *newtablesptr; int origsmbiosnum; // bitmask of used handles uint8_t handles[8192]; uint16_t nexthandle=0; int i, j; int tablespresent[256]; bool do_auto=true; extern void dumpPhysAddr(const char * title, void * a, int len); bzero(tablespresent, sizeof(tablespresent)); bzero(handles, sizeof(handles)); getBoolForKey(kSMBIOSdefaults, &do_auto, &bootInfo->bootConfig); newsmbios->dmi.tableAddress = (uint32_t)AllocateKernelMemory(newsmbios->dmi.tableLength); if (origsmbios) { smbiostables = (char *)origsmbios->dmi.tableAddress; origsmbiosnum = origsmbios->dmi.structureCount; } else { smbiostables = NULL; origsmbiosnum = 0; } tablesptr = smbiostables; newtablesptr = (char *)newsmbios->dmi.tableAddress; // if old smbios exists then update new smbios with old smbios original content first if (smbiostables) { for (i=0; i<origsmbiosnum; i++) { struct smbios_table_header *oldcur = (struct smbios_table_header *) tablesptr; struct smbios_table_header *newcur = (struct smbios_table_header *) newtablesptr; char *stringsptr; int nstrings = 0; handles[(oldcur->handle) / 8] |= 1 << ((oldcur->handle) % 8); // copy table length from old table to new table but not the old strings memcpy(newcur,oldcur, oldcur->length); tablesptr += oldcur->length; stringsptr = tablesptr; newtablesptr += oldcur->length; // calculate the number of strings in the old content for (;tablesptr[0]!=0 || tablesptr[1]!=0; tablesptr++) { if (tablesptr[0] == 0) { nstrings++; } } if (tablesptr != stringsptr) { nstrings++; } tablesptr += 2; // copy the old strings to new table memcpy(newtablesptr, stringsptr, tablesptr-stringsptr); // point to next possible space for a string (deducting the second 0 char at the end) newtablesptr += tablesptr - stringsptr - 1; if (nstrings == 0) { // if no string was found rewind to the first 0 char of the 0,0 terminator newtablesptr--; } // now for each property in the table update the overrides if any (auto or user) for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; int num; char altname[40]; sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1); if (smbios_properties[j].table_type == newcur->type) { switch (smbios_properties[j].value_type) { case SMSTRING: if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) { memcpy(newtablesptr, str, size); newtablesptr[size] = 0; newtablesptr += size + 1; *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; } else if (do_auto && smbios_properties[j].auto_str) { str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]); size = strlen(str); memcpy(newtablesptr, str, size); newtablesptr[size] = 0; newtablesptr += size + 1; *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; } break; case SMOWORD: if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) { int k=0, t=0, kk=0; const char *ptr = str; memset(((char*)newcur) + smbios_properties[j].offset, 0, 16); while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) { ptr++; } if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) { ptr += 2; } for (;ptr-str<size && *ptr && k<16;ptr++) { if (*ptr>='0' && *ptr<='9') { (t=(t<<4)|(*ptr-'0')),kk++; } if (*ptr>='a' && *ptr<='f') { (t=(t<<4)|(*ptr-'a'+10)),kk++; } if (*ptr>='A' && *ptr<='F') { (t=(t<<4)|(*ptr-'A'+10)),kk++; } if (kk == 2) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t; k++; kk = 0; t = 0; } } } break; case SMBYTE: if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; } else if (do_auto && smbios_properties[j].auto_int) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); } break; case SMWORD: if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) { *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; } else if (do_auto && smbios_properties[j].auto_int) { *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); } break; } } } if (nstrings == 0) { newtablesptr[0] = 0; newtablesptr++; } newtablesptr[0] = 0; newtablesptr++; tablespresent[newcur->type]++; } } // for each eventual complementary table not present in the original smbios, do the overrides for (i=0; i<sizeof(smbios_table_descriptions)/sizeof(smbios_table_descriptions[0]); i++) { int numnec = -1; char buffer[40]; sprintf(buffer, "SMtable%d", i); if (!getIntForKey(buffer, &numnec, &bootInfo->smbiosConfig)) { numnec = -1; } if (numnec == -1 && do_auto && smbios_table_descriptions[i].numfunc) { numnec = smbios_table_descriptions[i].numfunc(smbios_table_descriptions[i].type); } while (tablespresent[smbios_table_descriptions[i].type] < numnec) { struct smbios_table_header *newcur = (struct smbios_table_header *) newtablesptr; int nstrings = 0; memset(newcur,0, smbios_table_descriptions[i].len); while (handles[(nexthandle)/8] & (1 << ((nexthandle) % 8))) { nexthandle++; } newcur->handle = nexthandle; handles[nexthandle / 8] |= 1 << (nexthandle % 8); newcur->type = smbios_table_descriptions[i].type; newcur->length = smbios_table_descriptions[i].len; newtablesptr += smbios_table_descriptions[i].len; for (j=0; j<sizeof(smbios_properties)/sizeof(smbios_properties[0]); j++) { const char *str; int size; int num; char altname[40]; sprintf(altname, "%s_%d", smbios_properties[j].name, tablespresent[newcur->type] + 1); if (smbios_properties[j].table_type == newcur->type) { switch (smbios_properties[j].value_type) { case SMSTRING: if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) { memcpy(newtablesptr, str, size); newtablesptr[size] = 0; newtablesptr += size + 1; *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; } else if (do_auto && smbios_properties[j].auto_str) { str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]); size = strlen(str); memcpy(newtablesptr, str, size); newtablesptr[size] = 0; newtablesptr += size + 1; *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = ++nstrings; } break; case SMOWORD: if (getValueForKey(altname, &str, &size, &bootInfo->smbiosConfig) || getValueForKey(smbios_properties[j].name, &str, &size, &bootInfo->smbiosConfig)) { int k=0, t=0, kk=0; const char *ptr = str; memset(((char*)newcur) + smbios_properties[j].offset, 0, 16); while (ptr-str<size && *ptr && (*ptr==' ' || *ptr=='\t' || *ptr=='\n')) { ptr++; } if (size-(ptr-str)>=2 && ptr[0]=='0' && (ptr[1]=='x' || ptr[1]=='X')) { ptr += 2; } for (;ptr-str<size && *ptr && k<16;ptr++) { if (*ptr>='0' && *ptr<='9') { (t=(t<<4)|(*ptr-'0')),kk++; } if (*ptr>='a' && *ptr<='f') { (t=(t<<4)|(*ptr-'a'+10)),kk++; } if (*ptr>='A' && *ptr<='F') { (t=(t<<4)|(*ptr-'A'+10)),kk++; } if (kk == 2) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset + k)) = t; k++; kk = 0; t = 0; } } } break; case SMBYTE: if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; } else if (do_auto && smbios_properties[j].auto_int) { *((uint8_t*)(((char*)newcur) + smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); } break; case SMWORD: if (getIntForKey(altname, &num, &bootInfo->smbiosConfig) || getIntForKey(smbios_properties[j].name, &num, &bootInfo->smbiosConfig)) { *((uint16_t*)(((char*)newcur) + smbios_properties[j].offset)) = num; } else if (do_auto && smbios_properties[j].auto_int) { *((uint16_t*)(((char*)newcur)+smbios_properties[j].offset)) = smbios_properties[j].auto_int(smbios_properties[j].name, tablespresent[newcur->type]); } break; } } } if (nstrings == 0) { newtablesptr[0] = 0; newtablesptr++; } newtablesptr[0] = 0; newtablesptr++; tablespresent[smbios_table_descriptions[i].type]++; } } // calculate new checksums newsmbios->dmi.checksum = 0; newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi)); newsmbios->checksum = 0; newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios)); verbose("Patched DMI Table\n"); }
bool setOemProperties(IOService *provider) { SMBEntryPoint* eps = 0; IOMemoryDescriptor* dmiMemory = 0; IOItemCount dmiStructureCount = 0; UInt8* biosAddress = NULL; IOMemoryDescriptor * biosMemory = 0; IOMemoryMap * biosMap = 0; biosMemory = IOMemoryDescriptor::withPhysicalAddress( 0xf0000,0xfffff-0xf0000+1,kIODirectionOutIn); if(biosMemory) { biosMap = biosMemory->map(); if(biosMap) { biosAddress = (UInt8 *) biosMap->getVirtualAddress(); } } // Search 0x0f0000 - 0x0fffff for SMBIOS Ptr if(biosAddress) for (UInt32 Address = 0; Address < biosMap->getLength(); Address += 0x10) { if (*(UInt32 *)(biosAddress + Address) == SMBIOS_PTR) { eps = (SMBEntryPoint *)(biosAddress + Address); continue; } } if(eps) if (memcmp(eps->anchor, "_SM_", 4) == 0) { UInt8 csum; csum = checksum8(eps, sizeof(SMBEntryPoint)); /*HWSensorsDebugLog("DMI checksum = 0x%x", csum); HWSensorsDebugLog("DMI tableLength = %d", eps->dmi.tableLength); HWSensorsDebugLog("DMI tableAddress = 0x%x", (uint32_t) eps->dmi.tableAddress); HWSensorsDebugLog("DMI structureCount = %d", eps->dmi.structureCount); HWSensorsDebugLog("DMI bcdRevision = %x", eps->dmi.bcdRevision);*/ if (csum == 0 && eps->dmi.tableLength && eps->dmi.structureCount) { dmiStructureCount = eps->dmi.structureCount; dmiMemory = IOMemoryDescriptor::withPhysicalAddress( eps->dmi.tableAddress, eps->dmi.tableLength, kIODirectionOutIn ); } /*else { HWSensorsDebugLog("no DMI structure found"); }*/ } if (biosMap) OSSafeReleaseNULL(biosMap); if(biosMemory) OSSafeReleaseNULL(biosMemory); if ( dmiMemory ) { if (IOMemoryMap *fDMIMemoryMap = dmiMemory->map()) { decodeSMBIOSTable(provider, (void *) fDMIMemoryMap->getVirtualAddress(), fDMIMemoryMap->getLength(), dmiStructureCount ); OSSafeReleaseNULL(fDMIMemoryMap); } OSSafeReleaseNULL(dmiMemory); } return true; }
void setupSMBIOS(void) { _SMBIOS_DEBUG_DUMP("Entering setupSMBIOS(static)\n"); // Allocate 1 page of kernel memory (sufficient for a stripped SMBIOS table). void * kernelMemory = (void *)AllocateKernelMemory(4096); // Setup a new Entry Point Structure at the beginning of the newly allocated memory page. struct SMBEntryPoint * newEPS = (struct SMBEntryPoint *) kernelMemory; // Include additional/conditional code snippet. #include "smbios/static_data.h" newEPS->anchor[0] = 0x5f; // _ newEPS->anchor[1] = 0x53; // S newEPS->anchor[2] = 0x4d; // M newEPS->anchor[3] = 0x5f; // _ newEPS->checksum = 0; newEPS->entryPointLength = 0x1f; // sizeof(* newEPS) newEPS->majorVersion = 2; newEPS->minorVersion = 4; newEPS->maxStructureSize = STATIC_SMBIOS_SM_MAX_STRUCTURE_SIZE; // Defined in RevoBoot/i386/config/SMBIOS/data-template.h newEPS->entryPointRevision = 0; newEPS->formattedArea[0] = 0; newEPS->formattedArea[1] = 0; newEPS->formattedArea[2] = 0; newEPS->formattedArea[3] = 0; newEPS->formattedArea[4] = 0; newEPS->dmi.anchor[0] = 0x5f; // _ newEPS->dmi.anchor[1] = 0x44; // D newEPS->dmi.anchor[2] = 0x4d; // M newEPS->dmi.anchor[3] = 0x49; // I newEPS->dmi.anchor[4] = 0x5f; // _ newEPS->dmi.checksum = 0; newEPS->dmi.tableLength = tableLength; newEPS->dmi.tableAddress = (uint32_t) (kernelMemory + sizeof(struct SMBEntryPoint)); newEPS->dmi.bcdRevision = 0x24; newEPS->dmi.structureCount = STATIC_SMBIOS_DMI_STRUCTURE_COUNT; // Defined in RevoBoot/i386/config/SMBIOS/[data-template/MacModelNN].h // Safety measure to protect people from doing something that breaks the boot process. // #define FORCED_CHECK ((STATIC_SMBIOS_DMI_STRUCTURE_COUNT == 0) || (SET_MAX_STRUCTURE_LENGTH && (STATIC_SMBIOS_SM_MAX_STRUCTURE_SIZE == 0))) #define FORCED_CHECK ((STATIC_SMBIOS_DMI_STRUCTURE_COUNT == 0) || SET_MAX_STRUCTURE_LENGTH) #if (LOAD_MODEL_SPECIFIC_SMBIOS_DATA || FORCED_CHECK) /* * Get number of SMBIOS table structures from the loaded model specific SMBIOS data, or * when we have 0 values in: RevoBoot/i386/config/SMBIOS/[data-template/MacModelNN].bin */ if ((fileSize > 0) || FORCED_CHECK) { UInt16 structureCount = 0; char * structurePtr = (char *)newEPS->dmi.tableAddress; char * structureEnd = (structurePtr + newEPS->dmi.tableLength); while (structureEnd > (structurePtr + sizeof(SMBStructHeader))) { struct SMBStructHeader * header = (struct SMBStructHeader *) structurePtr; #if SET_MAX_STRUCTURE_LENGTH char * stringsPtr = structurePtr; #if DEBUG_SMBIOS SMBByte currentStructureType = header->type; #endif #endif // Skip the formatted area of the structure. structurePtr += header->length; /* * Skip the unformatted structure area at the end (strings). * Using word comparison instead of checking two bytes (thanks to Kabyl). */ for (; ((uint16_t *)structurePtr)[0] != 0; structurePtr++); // Adjust pointer after locating the double 0 terminator. structurePtr += 2; // Update structure counter. structureCount++; _SMBIOS_DEBUG_DUMP("structureCount: %d\n", structureCount); #if SET_MAX_STRUCTURE_LENGTH UInt16 maxStructureSize = (structurePtr - stringsPtr); if (newEPS->maxStructureSize < maxStructureSize) { newEPS->maxStructureSize = maxStructureSize; } _SMBIOS_DEBUG_DUMP("Structure (%d) length: %3d bytes.\n", currentStructureType, maxStructureSize); _SMBIOS_DEBUG_SLEEP(1); #endif // #if SET_MAX_STRUCTURE_LENGTH } // Uodate number of structures (boot hang without the correct value). newEPS->dmi.structureCount = structureCount; } #endif // #if (LOAD_MODEL_SPECIFIC_SMBIOS_DATA || FORCED_CHECK) /* * newEPS->dmi.tableLength represents the length of the static data, or the size * of the model specific SMBIOS data file from: /Extra/SMBIOS/MacModelNN.bin */ _SMBIOS_DEBUG_DUMP("newEPS->dmi.structureCount: %d\nnewEPS.dmi.tableLength: %d\n", newEPS->dmi.structureCount, newEPS->dmi.tableLength); // Take care of possible checksum errors newEPS->dmi.checksum = 256 - checksum8(&newEPS->dmi, sizeof(newEPS->dmi)); newEPS->checksum = 256 - checksum8(newEPS, sizeof(* newEPS)); // Used to update the EFI Configuration Table (in efi.c) which is // what AppleSMBIOS.kext reads to setup the SMBIOS table for OS X. gPlatform.SMBIOS.BaseAddress = (uint32_t) newEPS; _SMBIOS_DEBUG_DUMP("New SMBIOS replacement setup.\n"); _SMBIOS_DEBUG_SLEEP(5); }