From: erwan Date: Mon, 2 Mar 2009 22:31:25 +0000 (+0100) Subject: hdt:Cleaning DMI implementation X-Git-Tag: syslinux-3.74-pre4~18 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=15a182dda68c89e54235058822f5db9e4ba8675d;p=platform%2Fupstream%2Fsyslinux.git hdt:Cleaning DMI implementation Removing useless warnings by defining structures & functions properly Using existing types instead of u8,u16,u32 --- diff --git a/com32/lib/dmi/dmi.c b/com32/lib/dmi/dmi.c new file mode 100644 index 0000000..a2a08b5 --- /dev/null +++ b/com32/lib/dmi/dmi.c @@ -0,0 +1,600 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- +*/ + +#include +#include +#include "dmi/dmi.h" + +const char *out_of_spec = ""; +const char *bad_index = ""; + +void dmi_bios_runtime_size(uint32_t code, s_dmi *dmi) +{ + if(code&0x000003FF) { + dmi->bios.runtime_size=code; + strcpy(dmi->bios.runtime_size_unit,"bytes"); + } else { + dmi->bios.runtime_size=code >>10; + strcpy(dmi->bios.runtime_size_unit,"KB"); + + } +} + +void dmi_bios_characteristics(uint64_t code, s_dmi *dmi) +{ + int i; + /* + * This isn't very clear what this bit is supposed to mean + */ + //if(code.l&(1<<3)) + if(code&&(1<<3)) + { + ((bool *)(& dmi->bios.characteristics))[0]=true; + return; + } + + for(i=4; i<=31; i++) + //if(code.l&(1<bios.characteristics))[i-3]=true; +} + +void dmi_bios_characteristics_x1(uint8_t code, s_dmi *dmi) +{ + int i; + + for(i=0; i<=7; i++) + if(code&(1<bios.characteristics_x1))[i]=true; +} + +void dmi_bios_characteristics_x2(uint8_t code, s_dmi *dmi) +{ + int i; + + for(i=0; i<=2; i++) + if(code&(1<bios.characteristics_x2))[i]=true; +} + + +void dmi_system_uuid(uint8_t *p, s_dmi *dmi) +{ + int only0xFF=1, only0x00=1; + int i; + + for(i=0; i<16 && (only0x00 || only0xFF); i++) + { + if(p[i]!=0x00) only0x00=0; + if(p[i]!=0xFF) only0xFF=0; + } + + if(only0xFF) + { + sprintf(dmi->system.uuid,"Not Present"); + return; + } + if(only0x00) + { + sprintf(dmi->system.uuid,"Not Settable"); + return; + } + + sprintf(dmi->system.uuid,"%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], + p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); +} + +void dmi_system_wake_up_type(uint8_t code, s_dmi *dmi) +{ + /* 3.3.2.1 */ + static const char *type[]={ + "Reserved", /* 0x00 */ + "Other", + "Unknown", + "APM Timer", + "Modem Ring", + "LAN Remote", + "Power Switch", + "PCI PME#", + "AC Power Restored" /* 0x08 */ + }; + + if(code<=0x08) { + strcpy(dmi->system.wakeup_type,type[code]); + } else { + strcpy(dmi->system.wakeup_type,out_of_spec); + } +return; +} + +static void dmi_base_board_features(uint8_t code, s_dmi *dmi) +{ + if((code&0x1F)!=0) + { + int i; + + for(i=0; i<=4; i++) + if(code&(1<base_board.features))[i]=true; + } +} + +static void dmi_processor_voltage(uint8_t code, s_dmi *dmi) +{ + /* 3.3.5.4 */ + static const float voltage[]={ + 5.0, + 3.3, + 2.9 + }; + int i; + + if(code&0x80) + dmi->processor.voltage=((float)(code&0x7f)/10); + else + { + for(i=0; i<=2; i++) + if(code&(1<processor.voltage=voltage[i]; + } +} + +static void dmi_processor_id(uint8_t type, uint8_t *p, const char *version, s_dmi *dmi) +{ + /* + * Extra flags are now returned in the ECX register when one calls + * the CPUID instruction. Their meaning is explained in table 6, but + * DMI doesn't support this yet. + */ + uint32_t eax, edx; + int sig=0; + + /* + * This might help learn about new processors supporting the + * CPUID instruction or another form of identification. + */ + sprintf(dmi->processor.id,"ID: %02X %02X %02X %02X %02X %02X %02X %02X\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + + if(type==0x05) /* 80386 */ + { + uint16_t dx=WORD(p); + /* + * 80386 have a different signature. + */ + dmi->processor.signature.type=(dx >>12); + dmi->processor.signature.family=((dx>>8)&0xF); + dmi->processor.signature.stepping=(dx>>4)&0xF; + dmi->processor.signature.minor_stepping=(dx&0xF); + return; + } + if(type==0x06) /* 80486 */ + { + uint16_t dx=WORD(p); + /* + * Not all 80486 CPU support the CPUID instruction, we have to find + * wether the one we have here does or not. Note that this trick + * works only because we know that 80486 must be little-endian. + */ + if((dx&0x0F00)==0x0400 + && ((dx&0x00F0)==0x0040 || (dx&0x00F0)>=0x0070) + && ((dx&0x000F)>=0x0003)) + sig=1; + else + { + dmi->processor.signature.type=((dx >>12)&0x3); + dmi->processor.signature.family=((dx>>8)&0xF); + dmi->processor.signature.model=((dx>>4)&0xF); + dmi->processor.signature.stepping=(dx&0xF); + return; + } + } + else if((type>=0x0B && type<=0x13) /* Intel, Cyrix */ + || (type>=0xB0 && type<=0xB3) /* Intel */ + || type==0xB5 /* Intel */ + || type==0xB9) /* Intel */ + sig=1; + else if((type>=0x18 && type<=0x1D) /* AMD */ + || type==0x1F /* AMD */ + || (type>=0xB6 && type<=0xB7) /* AMD */ + || (type>=0x83 && type<=0x85)) /* AMD */ + sig=2; + else if(type==0x01 || type==0x02) + { + /* + * Some X86-class CPU have family "Other" or "Unknown". In this case, + * we use the version string to determine if they are known to + * support the CPUID instruction. + */ + if(strncmp(version, "Pentium III MMX", 15)==0) + sig=1; + else if(strncmp(version, "AMD Athlon(TM)", 14)==0 + || strncmp(version, "AMD Opteron(tm)", 15)==0) + sig=2; + else + return; + } + else /* not X86-class */ + return; + + eax=DWORD(p); + edx=DWORD(p+4); + switch(sig) + { + case 1: /* Intel */ + dmi->processor.signature.type=((eax >>12)&0x3); + dmi->processor.signature.family=(((eax>>16)&0xFF0)+((eax>>8)&0x00F)); + dmi->processor.signature.model=(((eax>>12)&0xF0)+((eax>>4)&0x0F)); + dmi->processor.signature.stepping=(eax&0xF); + break; + case 2: /* AMD */ + dmi->processor.signature.family=(((eax>>8)&0xF)==0xF?(eax>>20)&0xFF:(eax>>8)&0xF); + dmi->processor.signature.model =(((eax>>4)&0xF)==0xF?(eax>>16)&0xF :(eax>>4)&0xF); + dmi->processor.signature.stepping=(eax&0xF); + break; + } + + edx=DWORD(p+4); + if((edx&0x3FF7FDFF)!=0) + { + int i; + for(i=0; i<=31; i++) + if(cpu_flags_strings[i]!=NULL && edx&(1<processor.cpu_flags))[i]=true; + //printf("%s\t%s\n", prefix, flags[i]); + } +} + + +void to_dmi_header(struct dmi_header *h, uint8_t *data) +{ + h->type=data[0]; + h->length=data[1]; + h->handle=WORD(data+2); + h->data=data; +} + +const char *dmi_string(struct dmi_header *dm, uint8_t s) +{ + char *bp=(char *)dm->data; + size_t i, len; + + if(s==0) + return "Not Specified"; + + bp+=dm->length; + while(s>1 && *bp) + { + bp+=strlen(bp); + bp++; + s--; + } + + if(!*bp) + return bad_index; + + /* ASCII filtering */ + len=strlen(bp); + for(i=0; ibase_board,0,sizeof (s_base_board)); + memset(&dmi->battery,0,sizeof (s_battery)); + memset(&dmi->bios,0,sizeof (s_bios)); + memset(&dmi->chassis,0,sizeof (s_chassis)); + for (int i=0;imemory[i],0,sizeof (s_memory)); + memset(&dmi->processor,0,sizeof (s_processor)); + memset(&dmi->system,0,sizeof (s_system)); + + /* Until we found this elements in the dmitable, we consider them as not filled */ + dmi->base_board.filled=false; + dmi->battery.filled=false; + dmi->bios.filled=false; + dmi->chassis.filled=false; + for (int i=0;imemory[i].filled=false; + dmi->processor.filled=false; + dmi->system.filled=false; + + p=(char *)0xF0000; /* The start address to look at the dmi table */ + for (q = p; q < p + 0x10000; q += 16) { + memcpy(buf, q, 15); + if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) { + dmi->dmitable.num = buf[13]<<8|buf[12]; + dmi->dmitable.len = buf[7]<<8|buf[6]; + dmi->dmitable.base = buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; + dmi->dmitable.ver = (buf[0x06]<<8)+buf[0x07]; + + /* + * DMI version 0.0 means that the real version is taken from + * the SMBIOS version, which we don't know at this point. + */ + if(buf[14]!=0) { + dmi->dmitable.major_version=buf[14]>>4; + dmi->dmitable.minor_version=buf[14]&0x0F; + } + else { + dmi->dmitable.major_version=0; + dmi->dmitable.minor_version=0; + + } +/* printf("DMI present (version %d.%d)\n", dmitable.major_version,dmitable.minor_version); + printf("%d structures occupying %d bytes.\n",dmitable.num, dmitable.len); + printf("DMI table at 0x%08X.\n",dmitable.base);*/ + return DMI_TABLE_PRESENT; + } + } + dmi->dmitable.base=0; + dmi->dmitable.num=0; + dmi->dmitable.ver=0; + dmi->dmitable.len=0; + return -ENODMITABLE; +} + +void dmi_decode(struct dmi_header *h, uint16_t ver, s_dmi *dmi) +{ + uint8_t *data=h->data; + + /* + * Note: DMI types 37, 38 and 39 are untested + */ + switch(h->type) + { + case 0: /* 3.3.1 BIOS Information */ +// printf("BIOS Information\n"); + if(h->length<0x12) break; + dmi->bios.filled=true; + strcpy(dmi->bios.vendor,dmi_string(h,data[0x04])); + strcpy(dmi->bios.version,dmi_string(h,data[0x05])); + strcpy(dmi->bios.release_date,dmi_string(h,data[0x08])); + dmi->bios.address=WORD(data+0x06); + dmi_bios_runtime_size((0x10000-WORD(data+0x06))<<4,dmi); + dmi->bios.rom_size=(data[0x09]+1)<<6; + strcpy(dmi->bios.rom_size_unit,"kB"); + dmi_bios_characteristics(QWORD(data+0x0A),dmi); + + if(h->length<0x13) break; + dmi_bios_characteristics_x1(data[0x12], dmi); + if(h->length<0x14) break; + dmi_bios_characteristics_x2(data[0x13], dmi); + if(h->length<0x18) break; + if(data[0x14]!=0xFF && data[0x15]!=0xFF) + sprintf(dmi->bios.bios_revision,"%u.%u", + data[0x14], data[0x15]); + if(data[0x16]!=0xFF && data[0x17]!=0xFF) + sprintf(dmi->bios.firmware_revision,"%u.%u", + data[0x16], data[0x17]); + break; + case 1: /* 3.3.2 System Information */ +// printf("System Information\n"); + if(h->length<0x08) break; + dmi->system.filled=true; + strcpy(dmi->system.manufacturer,dmi_string(h,data[0x04])); + strcpy(dmi->system.product_name,dmi_string(h,data[0x05])); + strcpy(dmi->system.version,dmi_string(h,data[0x06])); + strcpy(dmi->system.serial,dmi_string(h,data[0x07])); + if(h->length<0x19) break; + dmi_system_uuid(data+0x08,dmi); + dmi_system_wake_up_type(data[0x18],dmi); + if(h->length<0x1B) break; + strcpy(dmi->system.sku_number,dmi_string(h,data[0x19])); + strcpy(dmi->system.family,dmi_string(h,data[0x1A])); + break; + + case 2: /* 3.3.3 Base Board Information */ +// printf("Base Board Information\n"); + if(h->length<0x08) break; + dmi->base_board.filled=true; + strcpy(dmi->base_board.manufacturer,dmi_string(h,data[0x04])); + strcpy(dmi->base_board.product_name,dmi_string(h,data[0x05])); + strcpy(dmi->base_board.version,dmi_string(h,data[0x06])); + strcpy(dmi->base_board.serial,dmi_string(h,data[0x07])); + if(h->length<0x0F) break; + strcpy(dmi->base_board.asset_tag,dmi_string(h,data[0x08])); + dmi_base_board_features(data[0x09], dmi); + strcpy(dmi->base_board.location,dmi_string(h,data[0x0A])); + strcpy(dmi->base_board.type,dmi_string(h,data[0x0D])); + if(h->length<0x0F+data[0x0E]*sizeof(uint16_t)) break; + break; + case 3: /* 3.3.4 Chassis Information */ +// printf("Chassis Information\n"); + if(h->length<0x09) break; + dmi->chassis.filled=true; + strcpy(dmi->chassis.manufacturer,dmi_string(h,data[0x04])); + strcpy(dmi->chassis.type,dmi_chassis_type(data[0x05]&0x7F)); + strcpy(dmi->chassis.lock,dmi_chassis_lock(data[0x05]>>7)); + strcpy(dmi->chassis.version,dmi_string(h,data[0x06])); + strcpy(dmi->chassis.serial,dmi_string(h,data[0x07])); + strcpy(dmi->chassis.asset_tag,dmi_string(h,data[0x08])); + if(h->length<0x0D) break; + strcpy(dmi->chassis.boot_up_state,dmi_chassis_state(data[0x09])); + strcpy(dmi->chassis.power_supply_state,dmi_chassis_state(data[0x0A])); + strcpy(dmi->chassis.thermal_state,dmi_chassis_state(data[0x0B])); + strcpy(dmi->chassis.security_status,dmi_chassis_security_status(data[0x0C])); + if(h->length<0x11) break; + sprintf(dmi->chassis.oem_information,"0x%08X\n",DWORD(data+0x0D)); + if(h->length<0x15) break; + dmi->chassis.height=data[0x11]; + dmi->chassis.nb_power_cords=data[0x12]; + break; + + case 4: /* 3.3.5 Processor Information */ +// printf("Processor Information\n"); + if(h->length<0x1A) break; + dmi->processor.filled=true; + strcpy(dmi->processor.socket_designation,dmi_string(h, data[0x04])); + strcpy(dmi->processor.type,dmi_processor_type(data[0x05])); + strcpy(dmi->processor.manufacturer,dmi_string(h, data[0x07])); + strcpy(dmi->processor.family,dmi_processor_family(data[0x06],dmi->processor.manufacturer)); + dmi_processor_id(data[0x06], data+8, dmi_string(h, data[0x10]), dmi); + strcpy(dmi->processor.version,dmi_string(h, data[0x10])); + dmi_processor_voltage(data[0x11],dmi); + dmi->processor.external_clock=WORD(data+0x12); + dmi->processor.max_speed=WORD(data+0x14); + dmi->processor.current_speed=WORD(data+0x16); + if(data[0x18]&(1<<6)) + strcpy(dmi->processor.status,dmi_processor_status(data[0x18]&0x07)); + else + sprintf(dmi->processor.status,"Unpopulated"); + sprintf(dmi->processor.upgrade,dmi_processor_upgrade(data[0x19])); + if(h->length<0x20) break; + dmi_processor_cache(WORD(data+0x1A), "L1", ver,dmi->processor.cache1); + dmi_processor_cache(WORD(data+0x1C), "L2", ver,dmi->processor.cache2); + dmi_processor_cache(WORD(data+0x1E), "L3", ver,dmi->processor.cache3); + if(h->length<0x23) break; + strcpy(dmi->processor.serial,dmi_string(h, data[0x20])); + strcpy(dmi->processor.asset_tag,dmi_string(h, data[0x21])); + strcpy(dmi->processor.part_number,dmi_string(h, data[0x22])); + break; + case 17: /* 3.3.18 Memory Device */ + if (h->length < 0x15) break; + dmi->memory_count++; + s_memory *mem = &dmi->memory[dmi->memory_count-1]; + dmi->memory[dmi->memory_count-1].filled=true; + dmi_memory_array_error_handle(WORD(data + 0x06),mem->error); + dmi_memory_device_width(WORD(data + 0x08),mem->total_width); + dmi_memory_device_width(WORD(data + 0x0A),mem->data_width); + dmi_memory_device_size(WORD(data + 0x0C),mem->size); + strcpy(mem->form_factor,dmi_memory_device_form_factor(data[0x0E])); + dmi_memory_device_set(data[0x0F],mem->device_set); + strcpy(mem->device_locator,dmi_string(h, data[0x10])); + strcpy(mem->bank_locator,dmi_string(h, data[0x11])); + strcpy(mem->type,dmi_memory_device_type(data[0x12])); + dmi_memory_device_type_detail(WORD(data + 0x13),mem->type_detail); + if (h->length < 0x17) break; + dmi_memory_device_speed(WORD(data + 0x15),mem->speed); + if (h->length < 0x1B) break; + strcpy(mem->manufacturer, dmi_string(h, data[0x17])); + strcpy(mem->serial,dmi_string(h, data[0x18])); + strcpy(mem->asset_tag,dmi_string(h, data[0x19])); + strcpy(mem->part_number,dmi_string(h, data[0x1A])); + break; + case 22: /* 3.3.23 Portable Battery */ + if (h->length < 0x10) break; + dmi->battery.filled=true; + strcpy(dmi->battery.location,dmi_string(h, data[0x04])); + strcpy(dmi->battery.manufacturer,dmi_string(h, data[0x05])); + + if (data[0x06] || h->length < 0x1A) + strcpy(dmi->battery.manufacture_date, dmi_string(h, data[0x06])); + + if (data[0x07] || h->length < 0x1A) + strcpy(dmi->battery.serial, dmi_string(h, data[0x07])); + + strcpy(dmi->battery.name,dmi_string(h, data[0x08])); + + if (data[0x09] != 0x02 || h->length < 0x1A) + strcpy(dmi->battery.chemistry,dmi_battery_chemistry(data[0x09])); + + if (h->length < 0x1A) + dmi_battery_capacity(WORD(data + 0x0A), 1,dmi->battery.design_capacity); + else + dmi_battery_capacity(WORD(data + 0x0A), data[0x15],dmi->battery.design_capacity); + dmi_battery_voltage(WORD(data + 0x0C),dmi->battery.design_voltage); + strcpy(dmi->battery.sbds,dmi_string(h, data[0x0E])); + dmi_battery_maximum_error(data[0x0F],dmi->battery.maximum_error); + if (h->length < 0x1A) break; + if (data[0x07] == 0) + sprintf(dmi->battery.sbds_serial,"%04X", WORD(data + 0x10)); + + if (data[0x06] == 0) + sprintf(dmi->battery.sbds_manufacture_date,"%u-%02u-%02u", + 1980 + (WORD(data + 0x12) >> 9), + (WORD(data + 0x12) >> 5) & 0x0F, + WORD(data + 0x12) & 0x1F); + if (data[0x09] == 0x02) + strcpy(dmi->battery.sbds_chemistry, dmi_string(h, data[0x14])); + + // sprintf(dmi->battery.oem_info,"0x%08X",DWORD(h, data+0x16)); + break; + + + } +} + +void parse_dmitable(s_dmi *dmi) { + int i=0; + uint8_t *data = NULL; + uint8_t buf[dmi->dmitable.len]; + + memcpy(buf,(int *)dmi->dmitable.base,sizeof(uint8_t) * dmi->dmitable.len); + data=buf; + dmi->memory_count=0; + while(idmitable.num && data+4<=buf+dmi->dmitable.len) /* 4 is the length of an SMBIOS structure header */ { + uint8_t *next; + struct dmi_header h; + to_dmi_header(&h, data); + + /* + * If a short entry is found (less than 4 bytes), not only it + * is invalid, but we cannot reliably locate the next entry. + * Better stop at this point, and let the user know his/her + * table is broken. + */ + if(h.length<4) + { + printf("Invalid entry length (%u). DMI table is broken! Stop.\n\n", (unsigned int)h.length); + break; + } + +// printf("Handle 0x%04X, DMI type %d, %d bytes\n", h.handle, h.type, h.length); + + /* loo for the next handle */ + next=data+h.length; + while(next-buf+1dmitable.len && (next[0]!=0 || next[1]!=0)) + next++; + next+=2; + if(next-buf<=dmi->dmitable.len) + { + dmi_decode(&h, dmi->dmitable.ver,dmi); + } + data=next; + i++; + } +} diff --git a/com32/lib/dmi/dmi_base_board.c b/com32/lib/dmi/dmi_base_board.c new file mode 100644 index 0000000..18250a2 --- /dev/null +++ b/com32/lib/dmi/dmi_base_board.c @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include +#include +const char *base_board_features_strings[]={ + "Board is a hosting board", /* 0 */ + "Board requires at least one daughter board", + "Board is removable", + "Board is replaceable", + "Board is hot swappable" /* 4 */ +}; + diff --git a/com32/lib/dmi/dmi_battery.c b/com32/lib/dmi/dmi_battery.c new file mode 100644 index 0000000..795fdfa --- /dev/null +++ b/com32/lib/dmi/dmi_battery.c @@ -0,0 +1,72 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include +#include +const char *dmi_battery_chemistry(uint8_t code) +{ + /* 3.3.23.1 */ + static const char *chemistry[] = { + "Other", /* 0x01 */ + "Unknown", + "Lead Acid", + "Nickel Cadmium", + "Nickel Metal Hydride", + "Lithium Ion", + "Zinc Air", + "Lithium Polymer" /* 0x08 */ + }; + + if (code >= 0x01 && code <= 0x08) + return chemistry[code - 0x01]; + return out_of_spec; +} + +void dmi_battery_capacity(uint16_t code, uint8_t multiplier,char *capacity) +{ + if (code == 0) + sprintf(capacity,"%s","Unknown"); + else + sprintf(capacity,"%u mWh", code * multiplier); +} + +void dmi_battery_voltage(uint16_t code, char *voltage) +{ + if (code == 0) + sprintf(voltage,"%s","Unknown"); + else + sprintf(voltage,"%u mV", code); +} + +void dmi_battery_maximum_error(uint8_t code, char *error) +{ + if (code == 0xFF) + sprintf(error,"%s","Unknown"); + else + sprintf(error,"%u%%", code); +} + diff --git a/com32/lib/dmi/dmi_bios.c b/com32/lib/dmi/dmi_bios.c new file mode 100644 index 0000000..1e281be --- /dev/null +++ b/com32/lib/dmi/dmi_bios.c @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include +#include + +const char *bios_charac_strings[]={ + "BIOS characteristics not supported", /* 3 */ + "ISA is supported", + "MCA is supported", + "EISA is supported", + "PCI is supported", + "PC Card (PCMCIA) is supported", + "PNP is supported", + "APM is supported", + "BIOS is upgradeable", + "BIOS shadowing is allowed", + "VLB is supported", + "ESCD support is available", + "Boot from CD is supported", + "Selectable boot is supported", + "BIOS ROM is socketed", + "Boot from PC Card (PCMCIA) is supported", + "EDD is supported", + "Japanese floppy for NEC 9800 1.2 MB is supported (int 13h)", + "Japanese floppy for Toshiba 1.2 MB is supported (int 13h)", + "5.25\"/360 KB floppy services are supported (int 13h)", + "5.25\"/1.2 MB floppy services are supported (int 13h)", + "3.5\"/720 KB floppy services are supported (int 13h)", + "3.5\"/2.88 MB floppy services are supported (int 13h)", + "Print screen service is supported (int 5h)", + "8042 keyboard services are supported (int 9h)", + "Serial services are supported (int 14h)", + "Printer services are supported (int 17h)", + "CGA/mono video services are supported (int 10h)", + "NEC PC-98" /* 31 */ +}; + +const char *bios_charac_x1_strings[]={ + "ACPI is supported", /* 0 */ + "USB legacy is supported", + "AGP is supported", + "I2O boot is supported", + "LS-120 boot is supported", + "ATAPI Zip drive boot is supported", + "IEEE 1394 boot is supported", + "Smart battery is supported" /* 7 */ +}; + +const char *bios_charac_x2_strings[]={ + "BIOS boot specification is supported", /* 0 */ + "Function key-initiated network boot is supported", + "Targeted content distribution is supported" /* 2 */ +}; + diff --git a/com32/lib/dmi/dmi_chassis.c b/com32/lib/dmi/dmi_chassis.c new file mode 100644 index 0000000..8cf3bf1 --- /dev/null +++ b/com32/lib/dmi/dmi_chassis.c @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include +#include + +const char *dmi_chassis_type(uint8_t code) +{ + /* 3.3.4.1 */ + static const char *type[]={ + "Other", /* 0x01 */ + "Unknown", + "Desktop", + "Low Profile Desktop", + "Pizza Box", + "Mini Tower", + "Tower", + "Portable", + "Laptop", + "Notebook", + "Hand Held", + "Docking Station", + "All In One", + "Sub Notebook", + "Space-saving", + "Lunch Box", + "Main Server Chassis", /* master.mif says System */ + "Expansion Chassis", + "Sub Chassis", + "Bus Expansion Chassis", + "Peripheral Chassis", + "RAID Chassis", + "Rack Mount Chassis", + "Sealed-case PC", + "Multi-system" /* 0x19 */ + }; + + if(code>=0x01 && code<=0x19) + return type[code-0x01]; + return out_of_spec; +} + +const char *dmi_chassis_lock(uint8_t code) +{ + static const char *lock[]={ + "Not Present", /* 0x00 */ + "Present" /* 0x01 */ + }; + + return lock[code]; +} + +const char *dmi_chassis_state(uint8_t code) +{ + /* 3.3.4.2 */ + static const char *state[]={ + "Other", /* 0x01 */ + "Unknown", + "Safe", /* master.mif says OK */ + "Warning", + "Critical", + "Non-recoverable" /* 0x06 */ + }; + + if(code>=0x01 && code<=0x06) + return(state[code-0x01]); + return out_of_spec; +} + +const char *dmi_chassis_security_status(uint8_t code) +{ + /* 3.3.4.3 */ + static const char *status[]={ + "Other", /* 0x01 */ + "Unknown", + "None", + "External Interface Locked Out", + "External Interface Enabled" /* 0x05 */ + }; + + if(code>=0x01 && code<=0x05) + return(status[code-0x01]); + return out_of_spec; +} diff --git a/com32/lib/dmi/dmi_memory.c b/com32/lib/dmi/dmi_memory.c new file mode 100644 index 0000000..86cc19d --- /dev/null +++ b/com32/lib/dmi/dmi_memory.c @@ -0,0 +1,171 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include +#include + +void dmi_memory_array_error_handle(uint16_t code,char *array) +{ + if (code == 0xFFFE) + sprintf(array,"%s","Not Provided"); + else if (code == 0xFFFF) + sprintf(array,"%s","No Error"); + else + sprintf(array,"0x%04X", code); +} + +void dmi_memory_device_width(uint16_t code, char *width) +{ + /* + * 3.3.18 Memory Device (Type 17) + * If no memory module is present, width may be 0 + */ + if (code == 0xFFFF || code == 0) + sprintf(width,"%s","Unknown"); + else + sprintf(width,"%u bits", code); +} + +void dmi_memory_device_size(uint16_t code, char *size) +{ + if (code == 0) + sprintf(size,"%s","Free"); + else if (code == 0xFFFF) + sprintf(size,"%s","Unknown"); + else { + if (code & 0x8000) + sprintf(size, "%u kB", code & 0x7FFF); + else + sprintf(size,"%u MB", code); + } +} + +const char *dmi_memory_device_form_factor(uint8_t code) +{ + /* 3.3.18.1 */ + static const char *form_factor[] = { + "Other", /* 0x01 */ + "Unknown", + "SIMM", + "SIP", + "Chip", + "DIP", + "ZIP", + "Proprietary Card", + "DIMM", + "TSOP", + "Row Of Chips", + "RIMM", + "SODIMM", + "SRIMM", + "FB-DIMM" /* 0x0F */ + }; + + if (code >= 0x01 && code <= 0x0F) + return form_factor[code - 0x01]; + return out_of_spec; +} + +void dmi_memory_device_set(uint8_t code, char *set) +{ + if (code == 0) + sprintf(set,"%s","None"); + else if (code == 0xFF) + sprintf(set,"%s","Unknown"); + else + sprintf(set,"%u", code); +} + +const char *dmi_memory_device_type(uint8_t code) +{ + /* 3.3.18.2 */ + static const char *type[] = { + "Other", /* 0x01 */ + "Unknown", + "DRAM", + "EDRAM", + "VRAM", + "SRAM", + "RAM", + "ROM", + "Flash", + "EEPROM", + "FEPROM", + "EPROM", + "CDRAM", + "3DRAM", + "SDRAM", + "SGRAM", + "RDRAM", + "DDR", + "DDR2", + "DDR2 FB-DIMM" /* 0x14 */ + }; + + if (code >= 0x01 && code <= 0x14) + return type[code - 0x01]; + return out_of_spec; +} + +void dmi_memory_device_type_detail(uint16_t code,char *type_detail) +{ + /* 3.3.18.3 */ + static const char *detail[] = { + "Other", /* 1 */ + "Unknown", + "Fast-paged", + "Static Column", + "Pseudo-static", + "RAMBus", + "Synchronous", + "CMOS", + "EDO", + "Window DRAM", + "Cache DRAM", + "Non-Volatile" /* 12 */ + }; + + if ((code & 0x1FFE) == 0) + sprintf(type_detail,"%s","None"); + else + { + int i; + + for (i = 1; i <= 12; i++) + if (code & (1 << i)) + sprintf(type_detail,"%s", detail[i - 1]); + } +} + +void dmi_memory_device_speed(uint16_t code, char *speed) +{ + if (code == 0) + sprintf(speed,"%s","Unknown"); + else + sprintf(speed,"%u MHz", code); +} + diff --git a/com32/lib/dmi/dmi_processor.c b/com32/lib/dmi/dmi_processor.c new file mode 100644 index 0000000..69606b0 --- /dev/null +++ b/com32/lib/dmi/dmi_processor.c @@ -0,0 +1,432 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2009 Erwan Velu - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * +*/ + +#include +#include + +const char *dmi_processor_type(uint8_t code) +{ + /* 3.3.5.1 */ + static const char *type[]={ + "Other", /* 0x01 */ + "Unknown", + "Central Processor", + "Math Processor", + "DSP Processor", + "Video Processor" /* 0x06 */ + }; + + if(code>=0x01 && code<=0x06) + return type[code-0x01]; + return out_of_spec; +} + +const char *dmi_processor_family(uint8_t code, char *manufacturer) +{ + /* 3.3.5.2 */ + static const char *family[]={ + NULL, /* 0x00 */ + "Other", + "Unknown", + "8086", + "80286", + "80386", + "80486", + "8087", + "80287", + "80387", + "80487", + "Pentium", + "Pentium Pro", + "Pentium II", + "Pentium MMX", + "Celeron", + "Pentium II Xeon", + "Pentium III", + "M1", + "M2", + "Celeron M", /* 0x14 */ + "Pentium 4 HT", + NULL, + NULL, /* 0x17 */ + "Duron", + "K5", + "K6", + "K6-2", + "K6-3", + "Athlon", + "AMD2900", + "K6-2+", + "Power PC", + "Power PC 601", + "Power PC 603", + "Power PC 603+", + "Power PC 604", + "Power PC 620", + "Power PC x704", + "Power PC 750", + "Core 2 Duo", /* 0x28 */ + "Core 2 Duo Mobile", + "Core Solo Mobile", + "Atom", + NULL, + NULL, + NULL, + NULL,/* 0x2F */ + "Alpha", + "Alpha 21064", + "Alpha 21066", + "Alpha 21164", + "Alpha 21164PC", + "Alpha 21164a", + "Alpha 21264", + "Alpha 21364", + NULL, /* 0x38 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x3F */ + "MIPS", + "MIPS R4000", + "MIPS R4200", + "MIPS R4400", + "MIPS R4600", + "MIPS R10000", + NULL, /* 0x46 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x4F */ + "SPARC", + "SuperSPARC", + "MicroSPARC II", + "MicroSPARC IIep", + "UltraSPARC", + "UltraSPARC II", + "UltraSPARC IIi", + "UltraSPARC III", + "UltraSPARC IIIi", + NULL, /* 0x59 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x5F */ + "68040", + "68xxx", + "68000", + "68010", + "68020", + "68030", + NULL, /* 0x66 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x6F */ + "Hobbit", + NULL, /* 0x71 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x77 */ + "Crusoe TM5000", + "Crusoe TM3000", + "Efficeon TM8000", + NULL, /* 0x7B */ + NULL, + NULL, + NULL, + NULL, /* 0x7F */ + "Weitek", + NULL, /* 0x81 */ + "Itanium", + "Athlon 64", + "Opteron", + "Sempron", + "Turion 64", /* 0x86 */ + "Dual-Core Opteron", + "Atlhon 64 X2", + "Turion 64 X2", + "Quad-Core Opteron", + "Third-Generation Opteron", + "Phenom FX", + "Phenom X4", + "Phenom X2", + "Athlon X2",/* 0x8F */ + "PA-RISC", + "PA-RISC 8500", + "PA-RISC 8000", + "PA-RISC 7300LC", + "PA-RISC 7200", + "PA-RISC 7100LC", + "PA-RISC 7100", + NULL, /* 0x97 */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0x9F */ + "V30", + "Quad-Core Xeon 3200", /* 0xA1 */ + "Dual-Core Xeon 3000", + "Quad-Core Xeon 5300", + "Dual-Core Xeon 5100", + "Dual-Core Xeon 5000", + "Dual-Core Xeon LV", + "Dual-Core Xeon ULV", + "Dual-Core Xeon 7100", + "Quad-Core Xeon 5400", + "Quad-Core Xeon", /* 0xAA */ + NULL, + NULL, + NULL, + NULL, + NULL, /* 0xAF */ + "Pentium III Xeon", + "Pentium III Speedstep", + "Pentium 4", + "Xeon", + "AS400", + "Xeon MP", + "Athlon XP", + "Athlon MP", + "Itanium 2", + "Pentium M", + "Celeron D", /* 0xBA */ + "Pentium D", + "Pentium EE", + "Core Solo", /* 0xBD */ + NULL, + "Core 2 Duo", + "Core 2 Solo", + "Core 2 Extreme", + "Core 2 Quad", + "Core 2 Extreme Mobile", + "Core 2 Duo Mobile", + "Core 2 Solo Mobile", + NULL, + NULL, /* 0xC7 */ + "IBM390", + "G4", + "G5", + "ESA/390 G6", /* 0xCB */ + "z/Architectur", + NULL, + NULL, + NULL, + NULL, /*0xD0*/ + NULL, + "C7-M", + "C7-D", + "C7", + "Eden", + NULL,/*0xD6*/ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /*0xE0*/ + NULL, + NULL, + NULL, + NULL, + NULL, + "Embedded Opteron Quad-Core",/* 0xE6*/ + "Phenom Triple-Core" , + "Turion Ultra Dual-Core Mobile", + "Turion Dual-Core Mobile", + "Athlon Dual-Core", + "Sempron SI",/*0xEB*/ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* 0xF9 */ + "i860", + "i960", + NULL, /* 0xFC */ + NULL, + NULL, + NULL /* 0xFF */ + /* master.mif has values beyond that, but they can't be used for DMI */ + }; + /* Special case for ambiguous value 0xBE */ + if (code == 0xBE) + { + /* Best bet based on manufacturer string */ + if (strstr(manufacturer, "Intel") != NULL + || strncasecmp(manufacturer, "Intel", 5) == 0) + return "Core 2"; + if (strstr(manufacturer, "AMD") != NULL + || strncasecmp(manufacturer, "AMD", 3) == 0) + return "K7"; + return "Core 2 or K7"; + } + + if(family[code]!=NULL) { + return family[code]; + } + return out_of_spec; +} + +const char *dmi_processor_status(uint8_t code) +{ + static const char *status[]={ + "Unknown", /* 0x00 */ + "Enabled", + "Disabled By User", + "Disabled By BIOS", + "Idle", /* 0x04 */ + "", + "", + "Other" /* 0x07 */ + }; + + if(code<=0x04) + return status[code]; + if(code==0x07) + return status[0x05]; + return out_of_spec; +} + +const char *dmi_processor_upgrade(uint8_t code) +{ + /* 3.3.5.5 */ + static const char *upgrade[]={ + "Other", /* 0x01 */ + "Unknown", + "Daughter Board", + "ZIF Socket", + "Replaceable Piggy Back", + "None", + "LIF Socket", + "Slot 1", + "Slot 2", + "370-pin Socket", + "Slot A", + "Slot M", + "Socket 423", + "Socket A (Socket 462)", + "Socket 478", + "Socket 754", + "Socket 940", + "Socket 939" /* 0x12 */ + "Socket mPGA604", + "Socket LGA771", + "Socket LGA775", + "Socket S1", + "Socket AM2", + "Socket F (1207)" + }; + + if(code>=0x01 && code<=0x11) + return upgrade[code-0x01]; + return out_of_spec; +} + +void dmi_processor_cache(uint16_t code, const char *level, uint16_t ver, char *cache) +{ + if(code==0xFFFF) + { + if(ver>=0x0203) + sprintf(cache,"Not Provided"); + else + sprintf(cache,"No %s Cache", level); + } + else + sprintf(cache,"0x%04X", code); +} + +/* Intel AP-485 revision 28, table 5 */ +const char *cpu_flags_strings[PROCESSOR_FLAGS_ELEMENTS]={ + "FPU (Floating-point unit on-chip)", /* 0 */ + "VME (Virtual mode extension)", + "DE (Debugging extension)", + "PSE (Page size extension)", + "TSC (Time stamp counter)", + "MSR (Model specific registers)", + "PAE (Physical address extension)", + "MCE (Machine check exception)", + "CX8 (CMPXCHG8 instruction supported)", + "APIC (On-chip APIC hardware supported)", + NULL, /* 10 */ + "SEP (Fast system call)", + "MTRR (Memory type range registers)", + "PGE (Page global enable)", + "MCA (Machine check architecture)", + "CMOV (Conditional move instruction supported)", + "PAT (Page attribute table)", + "PSE-36 (36-bit page size extension)", + "PSN (Processor serial number present and enabled)", + "CLFSH (CLFLUSH instruction supported)", + NULL, /* 20 */ + "DS (Debug store)", + "ACPI (ACPI supported)", + "MMX (MMX technology supported)", + "FXSR (Fast floating-point save and restore)", + "SSE (Streaming SIMD extensions)", + "SSE2 (Streaming SIMD extensions 2)", + "SS (Self-snoop)", + "HTT (Hyper-threading technology)", + "TM (Thermal monitor supported)", + "IA64 (IA64 capabilities)", /* 30 */ + "PBE (Pending break enabled)" /* 31 */ +}; +