Chameleon

Chameleon Commit Details

Date:2010-07-31 21:17:54 (13 years 8 months ago)
Author:Daniel Miranda
Commit:289
Parents: 288
Message:Initial import for UUID and label based volume specification
Changes:
M/branches/danielkza/i386/boot2/options.c
M/branches/danielkza/i386/libsaio/sys.c
M/branches/danielkza/i386/libsaio/xml.c
M/branches/danielkza/i386/libsaio/acpi_patcher.c
M/branches/danielkza/i386/libsaio/xml.h
M/branches/danielkza/i386/libsaio/disk.c

File differences

branches/danielkza/i386/libsaio/xml.c
110110
111111
112112
113
113114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
114172
115173
116174
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
branches/danielkza/i386/libsaio/xml.h
7373
7474
7575
76
7677
7778
7879
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.
branches/danielkza/i386/libsaio/acpi_patcher.c
269269
270270
271271
272
273
272
273
274274
275275
276276
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);
branches/danielkza/i386/libsaio/sys.c
6363
6464
6565
66
6667
68
6769
6870
6971
......
805807
806808
807809
810
808811
809812
810813
......
819822
820823
821824
822
825
823826
824827
825828
826
827
828
829
830
831
832
833
834
835
836
837
838
829839
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849840
850841
851842
......
10751066
10761067
10771068
1069
10781070
10791071
1080
1081
1072
1073
1074
10821075
10831076
10841077
10851078
1086
1079
1080
1081
1082
10871083
1088
1089
1090
1084
1085
10911086
10921087
1093
1088
10941089
#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 <Kernel/libkern/crypto/md5.h>
#else
//==========================================================================
BVRef selectBootVolume( BVRef chain )
{
bool filteredChain = false;
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.
//==========================================================================
// 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;
}
branches/danielkza/i386/libsaio/disk.c
6767
6868
6969
70
71
72
7073
7174
7275
......
15541557
15551558
15561559
1557
1558
1560
1561
15591562
1563
1564
1565
1566
1567
15601568
15611569
15621570
......
15891597
15901598
15911599
1592
1593
1600
15941601
15951602
1596
1597
1598
1599
1600
1601
1602
1603
1603
1604
1605
1606
1607
16041608
16051609
16061610
......
16291633
16301634
16311635
1636
1637
16321638
16331639
16341640
......
16791685
16801686
16811687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
16821752
1683
1753
16841754
1685
1686
1687
1688
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
16891798
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
17011823
17021824
1703
1825
17041826
1705
1706
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
17071841
1708
1709
1710
1711
1712
1842
1843
1844
1845
1846
17131847
1714
1715
1716
1717
1718
1719
1720
1721
17221848
17231849
17241850
17251851
17261852
1727
1728
1729
1853
1854
1855
17301856
1731
1732
1733
17341857
17351858
1736
1737
1738
1739
1740
1741
1742
1743
1744
1859
1860
1861
1862
1863
1864
1865
1866
1867
17451868
1746
1747
1748
1869
17491870
1750
1871
17511872
17521873
17531874
#include "msdos.h"
#include "ext2fs.h"
#include "xml.h"
#include "disk.h"
#include <limits.h>
#include <IOKit/storage/IOApplePartitionScheme.h>
#include <IOKit/storage/IOGUIDPartitionScheme.h>
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
)
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.
#endif
*count = bvCount;
free(val);
return chain;
}
//==========================================================================
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);
}
//==========================================================================
branches/danielkza/i386/boot2/options.c
111111
112112
113113
114
114
115115
116116
117117
......
777777
778778
779779
780
780
781781
782782
783783
......
854854
855855
856856
857
857
858858
859859
860860
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 );
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);
// 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;

Archive Download the corresponding diff file

Revision: 289