Index: branches/danielkza/i386/libsaio/xml.c =================================================================== --- branches/danielkza/i386/libsaio/xml.c (revision 288) +++ branches/danielkza/i386/libsaio/xml.c (revision 289) @@ -110,7 +110,65 @@ return 0; } +/* Function for basic XML entity replacement. It *does not* handle unicode escapes */ +char* +XMLDecode(const char* src) +{ + typedef const struct XMLEntity { + char* name; + size_t nameLen; + char value; + } XMLEntity; + + /* This is ugly, but better than specifying the lengths by hand */ + #define _e(str,c) {str,sizeof(str)-1,c} + const XMLEntity ents[] = { + _e("quot;",'"'), _e("apos;",'\''), + _e("lt;", '<'), _e("gt;", '>'), + _e("amp;", '&') + }; + + size_t len; + const char *s; + char *out, *o; + + if ( !src || !(len = strlen(src)) || !(out = malloc(len+1)) ) + return 0; + + o = out; + s = src; + while (s <= src+len) /* Make sure the terminator is also copied */ + { + if ( *s == '&' ) + { + bool entFound = false; + XMLEntity* ent; + int i = 0; + + s++; + for ( ent=&ents[0]; i < sizeof(ents); ent = &ents[i++] ) + { + if ( strncmp(s, ent->name, ent->nameLen) == 0 ) + { + entFound = true; + break; + } + } + if ( entFound ) + { + *o++ = ent->value; + s += ent->nameLen; + continue; + } + } + + *o++ = *s++; + } + + return out; +} + #if UNUSED //========================================================================== // XMLParseFile Index: branches/danielkza/i386/libsaio/xml.h =================================================================== --- branches/danielkza/i386/libsaio/xml.h (revision 288) +++ branches/danielkza/i386/libsaio/xml.h (revision 289) @@ -73,6 +73,7 @@ TagPtr XMLGetProperty( TagPtr dict, const char * key ); long XMLParseNextTag(char *buffer, TagPtr *tag); void XMLFreeTag(TagPtr tag); +char* XMLDecode(const char *in); //========================================================================== // XMLParseFile // Expects to see one dictionary in the XML file. Index: branches/danielkza/i386/libsaio/acpi_patcher.c =================================================================== --- branches/danielkza/i386/libsaio/acpi_patcher.c (revision 288) +++ branches/danielkza/i386/libsaio/acpi_patcher.c (revision 289) @@ -269,8 +269,8 @@ if (acpi_cpu_count > 0) { - bool c2_enabled = fadt->C2_Latency < 100; - bool c3_enabled = fadt->C3_Latency < 1000; + bool c2_enabled = (fadt->C2_Latency = 1) < 100; + bool c3_enabled = (fadt->C3_Latency = 100) < 1000; bool c4_enabled = false; getBoolForKey(kEnableC4States, &c4_enabled, &bootInfo->bootConfig); Index: branches/danielkza/i386/libsaio/sys.c =================================================================== --- branches/danielkza/i386/libsaio/sys.c (revision 288) +++ branches/danielkza/i386/libsaio/sys.c (revision 289) @@ -63,7 +63,9 @@ #include "libsaio.h" #include "boot.h" #include "bootstruct.h" +#include "disk.h" #include "ramdisk.h" +#include "xml.h" #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 # include #else @@ -805,6 +807,7 @@ //========================================================================== + BVRef selectBootVolume( BVRef chain ) { bool filteredChain = false; @@ -819,33 +822,21 @@ return bvr; /* - * Checking "Default Partition" key in system configuration - use format: hd(x,y) or the volume UUID - + * Checking "Default Partition" key in system configuration - use format: hd(x,y), the volume UUID or label - * to override the default selection. * We accept only kBVFlagSystemVolume or kBVFlagForeignBoot volumes. */ - const char * val; - char testStr[64]; - int cnt; + char *val = XMLDecode(getStringForKey(kDefaultPartition, &bootInfo->bootConfig)); + if (val) { + for ( bvr = chain; bvr; bvr = bvr->next ) { + if (matchVolumeToString(bvr, val, false)) { + free(val); + return bvr; + } + } + free(val); + } - if (getValueForKey(kDefaultPartition, &val, &cnt, &bootInfo->bootConfig) && cnt >= 7 && filteredChain) - { - for ( bvr = chain; bvr; bvr = bvr->next ) - { - if ( bvr->biosdev >= 0x80 && bvr->biosdev < 0x100 - && ( bvr->flags & ( kBVFlagSystemVolume|kBVFlagForeignBoot ) ) ) - { - // Trying to match hd(x,y) format. - sprintf(testStr, "hd(%d,%d)", bvr->biosdev - 0x80, bvr->part_no); - if (strcmp(testStr, val) == 0) - return bvr; - - // Trying to match volume UUID. - if (bvr->fs_getuuid && bvr->fs_getuuid(bvr, testStr) == 0 && strcmp(testStr, val) == 0) - return bvr; - } - } - } - /* * Scannig the volume chain backwards and trying to find * a HFS+ volume with valid boot record signature. @@ -1075,20 +1066,24 @@ //========================================================================== // getDeviceDescription() - Extracts unit number and partition number // from bvr structure into "dw(u,p)" format. +// Returns length of the out string int getDeviceDescription(BVRef bvr, char *str) { - const struct devsw *dp; - + if(!str) + return 0; + *str = '\0'; if (bvr) { - for (dp = devsw; dp->name && bvr->biosdev >= dp->biosdev; dp++); + const struct devsw *dp = devsw; + while(dp->name && bvr->biosdev >= dp->biosdev) + dp++; + dp--; - if (dp->name) sprintf(str, "%s(%d,%d)", dp->name, bvr->biosdev - dp->biosdev, bvr->part_no); - - return true; + if (dp->name) + return sprintf(str, "%s(%d,%d)", dp->name, bvr->biosdev - dp->biosdev, bvr->part_no); } - return false; + return 0; } Index: branches/danielkza/i386/libsaio/disk.c =================================================================== --- branches/danielkza/i386/libsaio/disk.c (revision 288) +++ branches/danielkza/i386/libsaio/disk.c (revision 289) @@ -67,6 +67,9 @@ #include "msdos.h" #include "ext2fs.h" +#include "xml.h" +#include "disk.h" + #include #include #include @@ -1554,9 +1557,14 @@ struct DiskBVMap * map = NULL; int bvCount = 0; - const char *val; - char devsw[12]; + const char *raw = 0; + char* val = 0; int len; + + getValueForKey(kHidePartition, &raw, &len, &bootInfo->bootConfig); + if(raw) { + val = XMLDecode(raw); + } /* * Traverse gDISKBVmap to get references for @@ -1589,18 +1597,14 @@ ) newBVR->visible = true; - /* - * Looking for "Hide Partition" entries in "hd(x,y) hd(n,m)" format + /* Looking for "Hide Partition" entries in 'hd(x,y)|uuid|"label" hd(m,n)|uuid|"label"' format * to be able to hide foreign partitions from the boot menu. */ - if ( (newBVR->flags & kBVFlagForeignBoot) - && getValueForKey(kHidePartition, &val, &len, &bootInfo->bootConfig) - ) - { - sprintf(devsw, "hd(%d,%d)", BIOS_DEV_UNIT(newBVR), newBVR->part_no); - if (strstr(val, devsw) != NULL) - newBVR->visible = false; - } + if ( (newBVR->flags & kBVFlagForeignBoot) ) + { + if(val && matchVolumeToString(newBVR, val, true)) + newBVR->visible = false; + } /* * Use the first bvr entry as the starting chain pointer. @@ -1629,6 +1633,8 @@ #endif *count = bvCount; + + free(val); return chain; } @@ -1679,75 +1685,190 @@ //========================================================================== +char* matchVolumeToString( BVRef bvr, const char* match, bool matchParcial) +{ + char testStr[64]; + + if ( !bvr || !match || !*match) + return false; + + if ( bvr->biosdev >= 0x80 && bvr->biosdev < 0x100 + && ( bvr->flags & ( kBVFlagSystemVolume|kBVFlagForeignBoot ) ) ) + { + // Trying to match hd(x,y) format. + int len; + char *ret = 0; + + len = sprintf(testStr, "hd(%d,%d)", BIOS_DEV_UNIT(bvr), bvr->part_no); + if (matchParcial) + ret = strstr(match, testStr); + else if (!strcmp(match, testStr)) + ret = (char*)match; + if(ret) + return ret+len; + + // Trying to match volume UUID. + if (bvr->fs_getuuid && bvr->fs_getuuid(bvr, testStr) == 0) + { + if (matchParcial) + ret = strstr(match, testStr); + else if (!strcmp(match, testStr)) + ret = (char*)match; + if (ret) + return ret+strlen(testStr); + } + + // Trying to match volume label (always quoted). + if (bvr->description) + { + char *ret = 0, *temp = 0; + + bvr->description(bvr, testStr, sizeof(testStr)-1); + if ( !(len = strlen(testStr)) ) + return 0; + + len+=2; /* quoted */ + temp = malloc(len+1); + if(!temp) + return 0; + + sprintf(temp, "\"%s\"", testStr); + + if(matchParcial) + ret = strstr(match, temp); + else if(!strcmp(match, temp)) + ret = (char*)match; + + free(temp); + + if(ret) + return ret+len; + } + } + + return 0; +} + /* If Rename Partition has defined an alias, then extract it for description purpose */ -static const char * getVolumeLabelAlias( BVRef bvr, const char * str, long strMaxLen) +bool getVolumeLabelAlias( BVRef bvr, char* str, long strMaxLen) { - const int MAX_ALIAS_SIZE=31; - static char szAlias[MAX_ALIAS_SIZE+1]; - char *q=szAlias; - const char * szAliases = getStringForKey(kRenamePartition, &bootInfo->bootConfig); + /* The format for the rename string is the following: + hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" etc; ... + */ + char *aliasList; + char *next; + if( !str || strMaxLen <= 0) + return false; + + if( !(aliasList = XMLDecode(getStringForKey(kRenamePartition, &bootInfo->bootConfig))) ) + return false; + + for(next = aliasList; + next && *next; + ) + { + char *start, *aliasStart, *aliasEnd; + char *ret; + + start = aliasStart = (char*)matchVolumeToString(bvr, next, true); + if(!start || !*start) + break; + + /* Find and delimit the current entry's end */ + next = strstr(start, ";"); + if(next) + { + /* Not enough characters for a successful match: we'd need at least + * one space and another char. before the semicolon + */ + if(next-start < 2) { + next++; + continue; + } + + *next = '\0'; + next++; + } + + /* Check for at least one space, but ignore the rest of them */ + while(isspace(*aliasStart)) + aliasStart++; + if(start == aliasStart) + continue; - if (!str || !*str || !szAliases) return 0; // no renaming wanted - - const char * p = strstr(szAliases, str); - if(!p || !(*p)) return 0; // this volume must not be renamed, or option is malformed - - p+= strlen(str); // skip the "hd(n,m) " field - // multiple aliases can be found separated by a semi-column - while(*p && *p != ';' && q<(szAlias+MAX_ALIAS_SIZE)) *q++=*p++; - *q='\0'; - - return szAlias; + switch(*aliasStart) + { + case '\0': + break; + /* If the string is quoted, skip the starting quote, find the ending + * one, and zero it to end the string. + * If we succeed, fall-through to the final copy-and-cleanup part */ + case '"': + aliasStart++; + aliasEnd = strstr(aliasStart, "\""); + if(!aliasEnd || aliasStart == aliasEnd) + break; + + *aliasEnd = '\0'; + default: + ret = strncpy(str, aliasStart, strMaxLen); + free(aliasList); + + return ret != 0; + } + } + + free(aliasList); + return false; } -void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen, bool verbose ) +void getBootVolumeDescription( BVRef bvr, char *str, long strMaxLen, bool verbose ) { - unsigned char type = (unsigned char) bvr->part_type; - char *p; + unsigned char type; + char*p = str; + + if(!bvr || !p || strMaxLen <= 0) + return; + + type = (unsigned char) bvr->part_type; + + if (verbose) + { + int len = getDeviceDescription(bvr, str); + strcat(str, " "); + for (; strMaxLen > 0 && *p != '\0'; p++, strMaxLen--); + } - p = str; - if (verbose) { - getDeviceDescription(bvr, str); - strcat(str, " "); - for (; strMaxLen > 0 && *p != '\0'; p++, strMaxLen--); + /* See if a partition rename is preferred */ + if(getVolumeLabelAlias(bvr, p, strMaxLen)) { + printf("Renamed: %s\n", p); + strncpy(bvr->label, p, sizeof(bvr->label)-1); + return; // we're done here no need to seek for real name } - - // See if we should get the renamed alias name for this partion: - const char * szAliasName = getVolumeLabelAlias(bvr, str, strMaxLen); - if (szAliasName && *szAliasName) - { - strncpy(bvr->label, szAliasName, strMaxLen); - return; // we're done here no need to seek for real name - } // // Get the volume label using filesystem specific functions // or use the alternate volume label if available. // - if (*bvr->altlabel == '\0') - { - if (bvr->description) + if (*bvr->altlabel != '\0') + strncpy(p, bvr->altlabel, strMaxLen); + else if (bvr->description) bvr->description(bvr, p, strMaxLen); - } - else - strncpy(p, bvr->altlabel, strMaxLen); if (*p == '\0') { - const char * name = getNameForValue( fdiskTypes, type ); - if (name == NULL) { - name = bvr->type_name; - } - if (name == NULL) { - sprintf(p, "TYPE %02x", type); - } else { - strncpy(p, name, strMaxLen); - } + const char * name = getNameForValue( fdiskTypes, type ); + if (name == NULL) { + name = bvr->type_name; + } + if (name == NULL) { + sprintf(p, "TYPE %02x", type); + } else { + strncpy(p, name, strMaxLen); + } } - - /* See if a partion rename is wanted: */ - + // Set the devices label - sprintf(bvr->label, p); + strncpy(bvr->label, p, sizeof(bvr->label)-1); } //========================================================================== Index: branches/danielkza/i386/boot2/options.c =================================================================== --- branches/danielkza/i386/boot2/options.c (revision 288) +++ branches/danielkza/i386/boot2/options.c (revision 289) @@ -111,7 +111,7 @@ position_t p = pos( gui.screen.width / 2 + 1 , ( gui.devicelist.pos.y + 3 ) + ( ( gui.devicelist.height - gui.devicelist.iconspacing ) / 2 ) ); char dummy[80]; - getBootVolumeDescription( gBootVolume, dummy, 80, true ); + getBootVolumeDescription( gBootVolume, dummy, 79, true ); drawDeviceIcon( gBootVolume, gui.screen.pixmap, p, false ); drawStrCenteredAt( (char *) msg, &font_small, gui.screen.pixmap, gui.countdown.pos ); @@ -777,7 +777,7 @@ strlcpy(prompt, val, cnt); } else { name = malloc(80); - getBootVolumeDescription(gBootVolume, name, 80, false); + getBootVolumeDescription(gBootVolume, name, 79, false); prompt = malloc(256); sprintf(prompt, "Press any key to start up from %s, or press F8 to enter startup options.", name); free(name); @@ -854,7 +854,7 @@ // Associate a menu item for each BVRef. for (bvr=bvChain, i=gDeviceCount-1, selectIndex=0; bvr; bvr=bvr->next) { if (bvr->visible) { - getBootVolumeDescription(bvr, menuItems[i].name, 80, true); + getBootVolumeDescription(bvr, menuItems[i].name, sizeof(menuItems[0].name)-1, true); menuItems[i].param = (void *) bvr; if (bvr == menuBVR) { selectIndex = i;