Index: branches/azimutz/Chazileon/doc/BootHelp.txt =================================================================== --- branches/azimutz/Chazileon/doc/BootHelp.txt (revision 417) +++ branches/azimutz/Chazileon/doc/BootHelp.txt (revision 418) @@ -55,13 +55,17 @@ Instant Menu=Yes Force displaying the partition selection menu. Default Partition Sets the default boot partition, - =hd(x,y)| where 'x' & 'y' are the disk and partition numbers - = or specify the selected volume UUID string. + =hd(x,y)|UUID|"Label" Specified as a disk/partition pair, an UUID, or a + label enclosed in quotes. + Hide Partition Remove unwanted partition(s) from the boot menu. - =hd(x,y) [hd(m,n)] only non mac osx boot partitions can be hidden. + =partition Specified, possibly multiple times, as hd(x,y), an + [;partition2 ...] UUID or label enclosed in quotes. Rename Partition Rename partition(s) for the boot menu. - =hd(x,y) [;hd(m,n) ...] + =partition Where partition is hd(x,y), UUID or label enclosed + [;partition2 in quotes. The alias can optionally be quoted too. + ...] GUI=No Disable the GUI (enabled by default). Boot Banner=Yes|No Show boot banner in GUI mode (enabled by default). Index: branches/azimutz/Chazileon/i386/libsaio/xml.c =================================================================== --- branches/azimutz/Chazileon/i386/libsaio/xml.c (revision 417) +++ branches/azimutz/Chazileon/i386/libsaio/xml.c (revision 418) @@ -110,7 +110,64 @@ return 0; } +/* Function for basic XML character entities parsing */ +char* +XMLDecode(const char* src) +{ + typedef const struct XMLEntity { + const 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; + int i; + + s++; + for ( i = 0; i < sizeof(ents); i++) + { + if ( strncmp(s, ents[i].name, ents[i].nameLen) == 0 ) + { + entFound = true; + break; + } + } + if ( entFound ) + { + *o++ = ents[i].value; + s += ents[i].nameLen; + continue; + } + } + + *o++ = *s++; + } + + return out; +} + #if UNUSED //========================================================================== // XMLParseFile Index: branches/azimutz/Chazileon/i386/libsaio/xml.h =================================================================== --- branches/azimutz/Chazileon/i386/libsaio/xml.h (revision 417) +++ branches/azimutz/Chazileon/i386/libsaio/xml.h (revision 418) @@ -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/azimutz/Chazileon/i386/libsaio/ntfs_private.h =================================================================== --- branches/azimutz/Chazileon/i386/libsaio/ntfs_private.h (revision 417) +++ branches/azimutz/Chazileon/i386/libsaio/ntfs_private.h (revision 418) @@ -275,8 +275,10 @@ cn_t bf_mftmirrcn; /* $MFTMirr cn */ u_int8_t bf_mftrecsz; /* MFT record size (clust) */ /* 0xF6 inducates 1/4 */ - u_int32_t bf_ibsz; /* index buffer size */ - u_int32_t bf_volsn; /* volume ser. num. */ + u_int8_t reserved5[3]; + u_int8_t bf_ibsz; /* index buffer size */ + u_int8_t reserved6[3]; + u_int64_t bf_volsn; /* volume ser. num. */ }; /* Index: branches/azimutz/Chazileon/i386/libsaio/ntfs.c =================================================================== --- branches/azimutz/Chazileon/i386/libsaio/ntfs.c (revision 417) +++ branches/azimutz/Chazileon/i386/libsaio/ntfs.c (revision 418) @@ -295,6 +295,41 @@ return; } +long NTFSGetUUID(CICell ih, char *uuidStr) +{ + bool NTFSProbe(const void*); + + struct bootfile *boot; + void *buf = malloc(MAX_BLOCK_SIZE); + if ( !buf ) + return -1; + + /* + * Read the boot sector, check signatures, and do some minimal + * sanity checking. NOTE: the size of the read below is intended + * to be a multiple of all supported block sizes, so we don't + * have to determine or change the device's block size. + */ + Seek(ih, 0); + Read(ih, (long)buf, MAX_BLOCK_SIZE); + + boot = (struct bootfile *) buf; + + // Check for NTFS signature + if ( memcmp((void*)boot->bf_sysid, NTFS_BBID, NTFS_BBIDLEN) != 0 ) + return -1; + + // Check for non-null volume serial number + if( !boot->bf_volsn ) + return -1; + + // Use UUID like the one you get on Windows + sprintf(uuidStr, "%04X-%04X", (unsigned short)(boot->bf_volsn >> 16) & 0xFFFF, + (unsigned short)boot->bf_volsn & 0xFFFF); + + return 0; +} + bool NTFSProbe(const void * buffer) { bool result = false; @@ -307,5 +342,3 @@ return result; } - - Index: branches/azimutz/Chazileon/i386/libsaio/sys.c =================================================================== --- branches/azimutz/Chazileon/i386/libsaio/sys.c (revision 417) +++ branches/azimutz/Chazileon/i386/libsaio/sys.c (revision 418) @@ -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 @@ -822,41 +824,28 @@ 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(kDefaultPartitionKey, &bootInfo->bootConfig)); + if (val) { + for ( bvr = chain; bvr; bvr = bvr->next ) { + if (matchVolumeToString(bvr, val, false)) { + free(val); + return bvr; + } + } + free(val); + } - if (getValueForKey(kDefaultPartitionKey, &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. * If not found any active partition then we will * select this volume as the boot volume. */ - for ( bvr = chain; bvr; bvr = bvr->next ) { if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) foundPrimary = true; @@ -1078,20 +1067,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/azimutz/Chazileon/i386/libsaio/ntfs.h =================================================================== --- branches/azimutz/Chazileon/i386/libsaio/ntfs.h (revision 417) +++ branches/azimutz/Chazileon/i386/libsaio/ntfs.h (revision 418) @@ -22,4 +22,4 @@ extern void NTFSGetDescription(CICell ih, char *str, long strMaxLen); extern bool NTFSProbe (const void *buf); - +extern long NTFSGetUUID(CICell ih, char *uuidStr); Index: branches/azimutz/Chazileon/i386/libsaio/disk.c =================================================================== --- branches/azimutz/Chazileon/i386/libsaio/disk.c (revision 417) +++ branches/azimutz/Chazileon/i386/libsaio/disk.c (revision 418) @@ -67,6 +67,9 @@ #include "msdos.h" #include "ext2fs.h" +#include "xml.h" +#include "disk.h" + #include #include #include @@ -874,7 +877,8 @@ biosdev, partno, part->relsect, part, - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + NTFSGetUUID, NTFSGetDescription, (BVFree)free, 0, kBIOSDevTypeHardDrive, 0); @@ -1548,78 +1552,94 @@ BVRef newFilteredBVChain(int minBIOSDev, int maxBIOSDev, unsigned int allowFlags, unsigned int denyFlags, int *count) { - BVRef chain = NULL; - BVRef bvr = NULL; - BVRef newBVR = NULL; - BVRef prevBVR = NULL; - - struct DiskBVMap * map = NULL; - int bvCount = 0; - - const char *val; - char devsw[12]; - int len; - - // Traverse gDISKBVmap to get references for - // individual bvr chains of each drive. - for (map = gDiskBVMap; map; map = map->next) - { - for (bvr = map->bvr; bvr; bvr = bvr->next) - { - // Save the last bvr. - if (newBVR) prevBVR = newBVR; - - // Allocate and copy the matched bvr entry into a new one. - newBVR = (BVRef) malloc(sizeof(*newBVR)); - bcopy(bvr, newBVR, sizeof(*newBVR)); - - // Adjust the new bvr's fields. - newBVR->next = NULL; - newBVR->filtered = true; - - if ((!allowFlags || newBVR->flags & allowFlags) && - (!denyFlags || !(newBVR->flags & denyFlags) ) && - (newBVR->biosdev >= minBIOSDev && newBVR->biosdev <= maxBIOSDev)) - { - newBVR->visible = true; - } - - // Looking for "Hide Partition" entries in "hd(x,y) hd(n,m)" format - // to be able to hide foreign partitions from the boot menu. - if ((newBVR->flags & kBVFlagForeignBoot) && - getValueForKey(kHidePartitionKey, &val, &len, &bootInfo->bootConfig)) - { - sprintf(devsw, "hd(%d,%d)", BIOS_DEV_UNIT(newBVR), newBVR->part_no); - if (strstr(val, devsw) != NULL) - { - newBVR->visible = false; - } - } - - // Use the first bvr entry as the starting chain pointer. - if (!chain) - chain = newBVR; - - // Update the previous bvr's link pointer to use the new memory area. - if (prevBVR) - prevBVR->next = newBVR; - - if (newBVR->visible) - bvCount++; - } - } + BVRef chain = NULL; + BVRef bvr = NULL; + BVRef newBVR = NULL; + BVRef prevBVR = NULL; + struct DiskBVMap * map = NULL; + int bvCount = 0; + + const char *raw = 0; + char* val = 0; + int len; + + getValueForKey(kHidePartitionKey, &raw, &len, &bootInfo->bootConfig); + if(raw) + { + val = XMLDecode(raw); + } + + /* + * Traverse gDISKBVmap to get references for + * individual bvr chains of each drive. + */ + for (map = gDiskBVMap; map; map = map->next) + { + for (bvr = map->bvr; bvr; bvr = bvr->next) + { + /* + * Save the last bvr. + */ + if (newBVR) prevBVR = newBVR; + + /* + * Allocate and copy the matched bvr entry into a new one. + */ + newBVR = (BVRef) malloc(sizeof(*newBVR)); + bcopy(bvr, newBVR, sizeof(*newBVR)); + + /* + * Adjust the new bvr's fields. + */ + newBVR->next = NULL; + newBVR->filtered = true; + + if ( (!allowFlags || newBVR->flags & allowFlags) + && (!denyFlags || !(newBVR->flags & denyFlags) ) + && (newBVR->biosdev >= minBIOSDev && newBVR->biosdev <= maxBIOSDev) + ) + newBVR->visible = true; + + /* 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) ) + { + if(val && matchVolumeToString(newBVR, val, true)) + newBVR->visible = false; + } + + /* + * Use the first bvr entry as the starting chain pointer. + */ + if (!chain) + chain = newBVR; + + /* + * Update the previous bvr's link pointer to use the new memory area. + */ + if (prevBVR) + prevBVR->next = newBVR; + + if (newBVR->visible) + bvCount++; + } + } + #if DEBUG - for (bvr = chain; bvr; bvr = bvr->next) - { - printf(" bvr: %d, dev: %d, part: %d, flags: %d, vis: %d\n", bvr, bvr->biosdev, bvr->part_no, bvr->flags, bvr->visible); - } - printf("count: %d\n", bvCount); - getc(); + for (bvr = chain; bvr; bvr = bvr->next) + { + printf(" bvr: %d, dev: %d, part: %d, flags: %d, vis: %d\n", bvr, bvr->biosdev, bvr->part_no, bvr->flags, bvr->visible); + } + printf("count: %d\n", bvCount); + getc(); #endif - *count = bvCount; - return chain; + *count = bvCount; + + free(val); + return chain; } int freeFilteredBVChain(const BVRef chain) @@ -1669,75 +1689,191 @@ //========================================================================== -/* If Rename Partition has defined an alias, then extract it for description purpose */ -static const char * getVolumeLabelAlias( BVRef bvr, const char * str, long strMaxLen) +static char * matchStrings(const char * str1, const char * str2, bool matchPartial) { - const int MAX_ALIAS_SIZE=31; - static char szAlias[MAX_ALIAS_SIZE+1]; - char *q=szAlias; - const char * szAliases = getStringForKey(kRenamePartitionKey, &bootInfo->bootConfig); + char * ret = NULL; - if (!str || !*str || !szAliases) return 0; // no renaming wanted + if (matchPartial) + ret = strstr(str1, str2); + else if (!strcmp(str1, str2)) + ret = (char *)str1; - const char * p = strstr(szAliases, str); - if(!p || !(*p)) return 0; // this volume must not be renamed, or option is malformed + if(ret) + ret += strlen(str2); - p+= strlen(str); // skip the "hd(n,m) " field - // multiple aliases can be found separated by a semicolon. - while(*p && *p != ';' && q<(szAlias+MAX_ALIAS_SIZE)) *q++=*p++; - *q='\0'; + return ret; +} - return szAlias; +char * matchVolumeToString(BVRef bvr, const char * match, bool matchPartial) +{ + char testStr[128]; + char tempStr[128]; + char * ret = NULL; + int len = 0; + + *tempStr = '\0'; + + if ( !bvr || !match || !*match) + return NULL; + + if ( bvr->biosdev < 0x80 || bvr->biosdev >= 0x100 + || !(bvr->flags & (kBVFlagSystemVolume|kBVFlagForeignBoot)) ) + return NULL; + + // Try to match hd(x,y) first. + sprintf(testStr, "hd(%d,%d)", BIOS_DEV_UNIT(bvr), bvr->part_no); + if (ret = matchStrings(match, testStr, matchPartial)) + return ret; + + // Try to match volume UUID. + if ( bvr->fs_getuuid && !(bvr->fs_getuuid(bvr, testStr)) ) + { + if (ret = matchStrings(match, testStr, matchPartial)) + return ret; + } + + // Try to match volume label (always quoted). + if (bvr->description) + { + // Gather volume label into tempStr. + bvr->description(bvr, tempStr, sizeof(tempStr) - 1); + len = strlen(tempStr); + if (len == 0) + return NULL; + + sprintf(testStr, "\"%s\"", tempStr); + if (ret = matchStrings(match, testStr, matchPartial)) + return ret; + } + + return NULL; } -void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen, bool verbose ) +/* If Rename Partition has defined an alias, then extract it for description purpose */ +bool getVolumeLabelAlias( BVRef bvr, char* str, long strMaxLen) { - unsigned char type = (unsigned char) bvr->part_type; - char *p; - - p = str; - if (verbose) { - getDeviceDescription(bvr, str); - strcat(str, " "); - for (; strMaxLen > 0 && *p != '\0'; p++, strMaxLen--); + /* The format for the rename string is the following: + * hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" etc; ... + */ + char *aliasList, *next; + + if ( !str || strMaxLen <= 0) + return false; + + aliasList = XMLDecode(getStringForKey(kRenamePartitionKey, &bootInfo->bootConfig)); + if ( !aliasList ) + return false; + + next = aliasList; + while ( 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; + + switch ( *aliasStart ) + { + case '\0': + break; + case '"': + /* If a starting quote is found, skip it, then find the ending one, + * and replace it for a string terminator. + */ + 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; +} - // See if we should get the renamed alias name for this partion: - const char * szAliasName = getVolumeLabelAlias(bvr, str, strMaxLen); - if (szAliasName && *szAliasName) +void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen, bool useDeviceDescription ) +{ + unsigned char type; + char *p = str; + + if(!bvr || !p || strMaxLen <= 0) + return; + + type = (unsigned char) bvr->part_type; + + if (useDeviceDescription) { - strncpy(bvr->label, szAliasName, strMaxLen); - return; // we're done here no need to seek for real name + int len = getDeviceDescription(bvr, str); + if(len >= strMaxLen) + return; + + strcpy(str + len, " "); + len++; + strMaxLen -= len; + p += len; } + + /* See if a partition rename is preferred */ + if(getVolumeLabelAlias(bvr, p, strMaxLen)) { + verbose("Renamed: %s\n", p); + strncpy(bvr->label, p, sizeof(bvr->label) - 1); + 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/azimutz/Chazileon/i386/libsaio/disk.h =================================================================== --- branches/azimutz/Chazileon/i386/libsaio/disk.h (revision 0) +++ branches/azimutz/Chazileon/i386/libsaio/disk.h (revision 418) @@ -0,0 +1,14 @@ +/* + * disk.h + * Chameleon + * + * Created by Daniel Miranda on 27/07/10. + * Copyright 2010 __MyCompanyName__. All rights reserved. + * + */ +#ifndef __LIBSAIO_DISK_H +#define __LIBSAIO_DISK_H + +char* matchVolumeToString( BVRef bvr, const char* match, bool matchPartial); + +#endif /* __LIBSAIO_DISK_H */ \ No newline at end of file Property changes on: branches/azimutz/Chazileon/i386/libsaio/disk.h ___________________________________________________________________ Added: svn:executable + * Index: branches/azimutz/Chazileon/i386/libsaio/saio_types.h =================================================================== --- branches/azimutz/Chazileon/i386/libsaio/saio_types.h (revision 417) +++ branches/azimutz/Chazileon/i386/libsaio/saio_types.h (revision 418) @@ -136,7 +136,7 @@ typedef long (*FSGetDirEntry)(CICell ih, char * dirPath, long long * dirIndex, char ** name, long * flags, long * time, FinderInfo * finderInfo, long * infoValid); -typedef long (* FSGetUUID)(CICell ih, char *uuidStr); +typedef long (*FSGetUUID)(CICell ih, char *uuidStr); typedef void (*BVGetDescription)(CICell ih, char * str, long strMaxLen); // Can be just pointed to free or a special free function typedef void (*BVFree)(CICell ih); Index: branches/azimutz/Chazileon/i386/boot2/options.c =================================================================== --- branches/azimutz/Chazileon/i386/boot2/options.c (revision 417) +++ branches/azimutz/Chazileon/i386/boot2/options.c (revision 418) @@ -117,7 +117,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, sizeof(dummy) - 1, true ); drawDeviceIcon( gBootVolume, gui.screen.pixmap, p, true ); drawStrCenteredAt( (char *) msg, &font_small, gui.screen.pixmap, gui.countdown.pos ); @@ -787,7 +787,7 @@ strlcpy(prompt, val, cnt); } else { name = malloc(80); - getBootVolumeDescription(gBootVolume, name, 80, false); + getBootVolumeDescription(gBootVolume, name, sizeof(name) - 1, false); prompt = malloc(256); sprintf(prompt, "Press any key to start up from %s, or press F8 to enter startup options.", name); free(name); @@ -864,7 +864,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; Index: branches/azimutz/CleanCut/doc/BootHelp.txt =================================================================== --- branches/azimutz/CleanCut/doc/BootHelp.txt (revision 417) +++ branches/azimutz/CleanCut/doc/BootHelp.txt (revision 418) @@ -51,13 +51,17 @@ Instant Menu=Yes Force displaying the partition selection menu. Default Partition Sets the default boot partition, - =hd(x,y)| where 'x' & 'y' are the disk and partition numbers - = or specify the selected volume UUID string. + =hd(x,y)|UUID|"Label" Specified as a disk/partition pair, an UUID, or a + label enclosed in quotes. + Hide Partition Remove unwanted partition(s) from the boot menu. - =hd(x,y) [hd(m,n)] only non mac osx boot partitions can be hidden. + =partition Specified, possibly multiple times, as hd(x,y), an + [;partition2 ...] UUID or label enclosed in quotes. Rename Partition Rename partition(s) for the boot menu. - =hd(x,y) [;hd(m,n) ...] + =partition Where partition is hd(x,y), UUID or label enclosed + [;partition2 in quotes. The alias can optionally be quoted too. + ...] GUI=No Disable the GUI (enabled by default). Boot Banner=Yes|No Show boot banner in GUI mode (enabled by default). Index: branches/azimutz/CleanCut/i386/libsaio/xml.c =================================================================== --- branches/azimutz/CleanCut/i386/libsaio/xml.c (revision 417) +++ branches/azimutz/CleanCut/i386/libsaio/xml.c (revision 418) @@ -110,7 +110,64 @@ return 0; } +/* Function for basic XML character entities parsing */ +char* +XMLDecode(const char* src) +{ + typedef const struct XMLEntity { + const 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; + int i; + + s++; + for ( i = 0; i < sizeof(ents); i++) + { + if ( strncmp(s, ents[i].name, ents[i].nameLen) == 0 ) + { + entFound = true; + break; + } + } + if ( entFound ) + { + *o++ = ents[i].value; + s += ents[i].nameLen; + continue; + } + } + + *o++ = *s++; + } + + return out; +} + #if UNUSED //========================================================================== // XMLParseFile Index: branches/azimutz/CleanCut/i386/libsaio/xml.h =================================================================== --- branches/azimutz/CleanCut/i386/libsaio/xml.h (revision 417) +++ branches/azimutz/CleanCut/i386/libsaio/xml.h (revision 418) @@ -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/azimutz/CleanCut/i386/libsaio/ntfs_private.h =================================================================== --- branches/azimutz/CleanCut/i386/libsaio/ntfs_private.h (revision 417) +++ branches/azimutz/CleanCut/i386/libsaio/ntfs_private.h (revision 418) @@ -275,8 +275,10 @@ cn_t bf_mftmirrcn; /* $MFTMirr cn */ u_int8_t bf_mftrecsz; /* MFT record size (clust) */ /* 0xF6 inducates 1/4 */ - u_int32_t bf_ibsz; /* index buffer size */ - u_int32_t bf_volsn; /* volume ser. num. */ + u_int8_t reserved5[3]; + u_int8_t bf_ibsz; /* index buffer size */ + u_int8_t reserved6[3]; + u_int64_t bf_volsn; /* volume ser. num. */ }; /* Index: branches/azimutz/CleanCut/i386/libsaio/ntfs.c =================================================================== --- branches/azimutz/CleanCut/i386/libsaio/ntfs.c (revision 417) +++ branches/azimutz/CleanCut/i386/libsaio/ntfs.c (revision 418) @@ -295,6 +295,41 @@ return; } +long NTFSGetUUID(CICell ih, char *uuidStr) +{ + bool NTFSProbe(const void*); + + struct bootfile *boot; + void *buf = malloc(MAX_BLOCK_SIZE); + if ( !buf ) + return -1; + + /* + * Read the boot sector, check signatures, and do some minimal + * sanity checking. NOTE: the size of the read below is intended + * to be a multiple of all supported block sizes, so we don't + * have to determine or change the device's block size. + */ + Seek(ih, 0); + Read(ih, (long)buf, MAX_BLOCK_SIZE); + + boot = (struct bootfile *) buf; + + // Check for NTFS signature + if ( memcmp((void*)boot->bf_sysid, NTFS_BBID, NTFS_BBIDLEN) != 0 ) + return -1; + + // Check for non-null volume serial number + if( !boot->bf_volsn ) + return -1; + + // Use UUID like the one you get on Windows + sprintf(uuidStr, "%04X-%04X", (unsigned short)(boot->bf_volsn >> 16) & 0xFFFF, + (unsigned short)boot->bf_volsn & 0xFFFF); + + return 0; +} + bool NTFSProbe(const void * buffer) { bool result = false; @@ -307,5 +342,3 @@ return result; } - - Index: branches/azimutz/CleanCut/i386/libsaio/sys.c =================================================================== --- branches/azimutz/CleanCut/i386/libsaio/sys.c (revision 417) +++ branches/azimutz/CleanCut/i386/libsaio/sys.c (revision 418) @@ -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 @@ -819,33 +821,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 +1065,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/azimutz/CleanCut/i386/libsaio/ntfs.h =================================================================== --- branches/azimutz/CleanCut/i386/libsaio/ntfs.h (revision 417) +++ branches/azimutz/CleanCut/i386/libsaio/ntfs.h (revision 418) @@ -22,4 +22,4 @@ extern void NTFSGetDescription(CICell ih, char *str, long strMaxLen); extern bool NTFSProbe (const void *buf); - +extern long NTFSGetUUID(CICell ih, char *uuidStr); Index: branches/azimutz/CleanCut/i386/libsaio/disk.c =================================================================== --- branches/azimutz/CleanCut/i386/libsaio/disk.c (revision 417) +++ branches/azimutz/CleanCut/i386/libsaio/disk.c (revision 418) @@ -67,6 +67,9 @@ #include "msdos.h" #include "ext2fs.h" +#include "xml.h" +#include "disk.h" + #include #include #include @@ -874,7 +877,8 @@ biosdev, partno, part->relsect, part, - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + NTFSGetUUID, NTFSGetDescription, (BVFree)free, 0, kBIOSDevTypeHardDrive, 0); @@ -1256,7 +1260,7 @@ // NOTE: EFI_GUID's are in LE and we know we're on an x86. // The IOGUIDPartitionScheme.cpp code uses byte-based UUIDs, we don't. - if(isPartitionUsed(gptMap)) + if (isPartitionUsed(gptMap)) { char stringuuid[100]; efi_guid_unparse_upper((EFI_GUID*)gptMap->ent_type, stringuuid); @@ -1556,9 +1560,15 @@ 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 @@ -1591,18 +1601,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. @@ -1631,6 +1637,8 @@ #endif *count = bvCount; + + free(val); return chain; } @@ -1681,75 +1689,191 @@ //========================================================================== -/* If Rename Partition has defined an alias, then extract it for description purpose */ -static const char * getVolumeLabelAlias( BVRef bvr, const char * str, long strMaxLen) +static char * matchStrings(const char * str1, const char * str2, bool matchPartial) { - const int MAX_ALIAS_SIZE=31; - static char szAlias[MAX_ALIAS_SIZE+1]; - char *q=szAlias; - const char * szAliases = getStringForKey(kRenamePartition, &bootInfo->bootConfig); + char * ret = NULL; - if (!str || !*str || !szAliases) return 0; // no renaming wanted + if (matchPartial) + ret = strstr(str1, str2); + else if (!strcmp(str1, str2)) + ret = (char *)str1; - const char * p = strstr(szAliases, str); - if(!p || !(*p)) return 0; // this volume must not be renamed, or option is malformed + if(ret) + ret += strlen(str2); - p+= strlen(str); // skip the "hd(n,m) " field - // multiple aliases can be found separated by a semicolon. - while(*p && *p != ';' && q<(szAlias+MAX_ALIAS_SIZE)) *q++=*p++; - *q='\0'; + return ret; +} - return szAlias; +char * matchVolumeToString(BVRef bvr, const char * match, bool matchPartial) +{ + char testStr[128]; + char tempStr[128]; + char * ret = NULL; + int len = 0; + + *tempStr = '\0'; + + if ( !bvr || !match || !*match) + return NULL; + + if ( bvr->biosdev < 0x80 || bvr->biosdev >= 0x100 + || !(bvr->flags & (kBVFlagSystemVolume|kBVFlagForeignBoot)) ) + return NULL; + + // Try to match hd(x,y) first. + sprintf(testStr, "hd(%d,%d)", BIOS_DEV_UNIT(bvr), bvr->part_no); + if (ret = matchStrings(match, testStr, matchPartial)) + return ret; + + // Try to match volume UUID. + if ( bvr->fs_getuuid && !(bvr->fs_getuuid(bvr, testStr)) ) + { + if (ret = matchStrings(match, testStr, matchPartial)) + return ret; + } + + // Try to match volume label (always quoted). + if (bvr->description) + { + // Gather volume label into tempStr. + bvr->description(bvr, tempStr, sizeof(tempStr) - 1); + len = strlen(tempStr); + if (len == 0) + return NULL; + + sprintf(testStr, "\"%s\"", tempStr); + if (ret = matchStrings(match, testStr, matchPartial)) + return ret; + } + + return NULL; } -void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen, bool verbose ) +/* If Rename Partition has defined an alias, then extract it for description purpose */ +bool getVolumeLabelAlias( BVRef bvr, char* str, long strMaxLen) { - unsigned char type = (unsigned char) bvr->part_type; - char *p; - - p = str; - if (verbose) { - getDeviceDescription(bvr, str); - strcat(str, " "); - for (; strMaxLen > 0 && *p != '\0'; p++, strMaxLen--); + /* The format for the rename string is the following: + * hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" etc; ... + */ + char *aliasList, *next; + + if ( !str || strMaxLen <= 0) + return false; + + aliasList = XMLDecode(getStringForKey(kRenamePartition, &bootInfo->bootConfig)); + if ( !aliasList ) + return false; + + next = aliasList; + while ( 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; + + switch ( *aliasStart ) + { + case '\0': + break; + case '"': + /* If a starting quote is found, skip it, then find the ending one, + * and replace it for a string terminator. + */ + 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; +} - // See if we should get the renamed alias name for this partion: - const char * szAliasName = getVolumeLabelAlias(bvr, str, strMaxLen); - if (szAliasName && *szAliasName) +void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen, bool useDeviceDescription ) +{ + unsigned char type; + char *p = str; + + if(!bvr || !p || strMaxLen <= 0) + return; + + type = (unsigned char) bvr->part_type; + + if (useDeviceDescription) { - strncpy(bvr->label, szAliasName, strMaxLen); - return; // we're done here no need to seek for real name + int len = getDeviceDescription(bvr, str); + if(len >= strMaxLen) + return; + + strcpy(str + len, " "); + len++; + strMaxLen -= len; + p += len; } + + /* See if a partition rename is preferred */ + if(getVolumeLabelAlias(bvr, p, strMaxLen)) { + verbose("Renamed: %s\n", p); + strncpy(bvr->label, p, sizeof(bvr->label) - 1); + 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/azimutz/CleanCut/i386/libsaio/disk.h =================================================================== --- branches/azimutz/CleanCut/i386/libsaio/disk.h (revision 0) +++ branches/azimutz/CleanCut/i386/libsaio/disk.h (revision 418) @@ -0,0 +1,14 @@ +/* + * disk.h + * Chameleon + * + * Created by Daniel Miranda on 27/07/10. + * Copyright 2010 __MyCompanyName__. All rights reserved. + * + */ +#ifndef __LIBSAIO_DISK_H +#define __LIBSAIO_DISK_H + +char* matchVolumeToString( BVRef bvr, const char* match, bool matchPartial); + +#endif /* __LIBSAIO_DISK_H */ \ No newline at end of file Property changes on: branches/azimutz/CleanCut/i386/libsaio/disk.h ___________________________________________________________________ Added: svn:executable + * Index: branches/azimutz/CleanCut/i386/libsaio/saio_types.h =================================================================== --- branches/azimutz/CleanCut/i386/libsaio/saio_types.h (revision 417) +++ branches/azimutz/CleanCut/i386/libsaio/saio_types.h (revision 418) @@ -135,7 +135,7 @@ typedef long (*FSGetDirEntry)(CICell ih, char * dirPath, long long * dirIndex, char ** name, long * flags, long * time, FinderInfo * finderInfo, long * infoValid); -typedef long (* FSGetUUID)(CICell ih, char *uuidStr); +typedef long (*FSGetUUID)(CICell ih, char *uuidStr); typedef void (*BVGetDescription)(CICell ih, char * str, long strMaxLen); // Can be just pointed to free or a special free function typedef void (*BVFree)(CICell ih); Index: branches/azimutz/CleanCut/i386/boot2/options.c =================================================================== --- branches/azimutz/CleanCut/i386/boot2/options.c (revision 417) +++ branches/azimutz/CleanCut/i386/boot2/options.c (revision 418) @@ -113,7 +113,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, sizeof(dummy) - 1, true ); drawDeviceIcon( gBootVolume, gui.screen.pixmap, p, true ); drawStrCenteredAt( (char *) msg, &font_small, gui.screen.pixmap, gui.countdown.pos ); @@ -783,7 +783,7 @@ strlcpy(prompt, val, cnt); } else { name = malloc(80); - getBootVolumeDescription(gBootVolume, name, 80, false); + getBootVolumeDescription(gBootVolume, name, sizeof(name) - 1, false); prompt = malloc(256); sprintf(prompt, "Press any key to start up from %s, or press F8 to enter startup options.", name); free(name); @@ -860,7 +860,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;