Chameleon

Chameleon Commit Details

Date:2010-08-02 00:27:32 (13 years 8 months ago)
Author:Azimutz
Commit:298
Parents: 297
Message:Matching trunk rev 295.
Changes:
M/branches/azimutz/CleanCut/i386/libsaio/acpi_patcher.c
M/branches/azimutz/CleanCut/i386/libsaio/smbios_patcher.c
M/branches/azimutz/CleanCut/i386/libsaio/cache.c
M/branches/azimutz/CleanCut/i386/libsaio/memvendors.h
M/branches/azimutz/CleanCut/i386/libsa/memory.h
M/branches/azimutz/CleanCut/i386/libsaio/msdos.c
M/branches/azimutz/CleanCut/i386/libsaio/dram_controllers.c
M/branches/azimutz/CleanCut/CHANGES

File differences

branches/azimutz/CleanCut/CHANGES
1
2
13
24
35
- Added automatic SMBusspeed detection for lga1156 core i5/7 cpus
- Added new iMac11,1 sbios default model for lga1156 core i5/17 mobos
- md0 code. Notified xnu when an md ramdisk is specified
- Added rollover image support for selected device icons.
Use device_<type>_o.png in theme folder. Credits goes to Blackosx.
branches/azimutz/CleanCut/i386/libsaio/acpi_patcher.c
387387
388388
389389
390
390
391391
392
392
393393
394394
395395
......
400400
401401
402402
403
404
405
403406
404407
405408
406409
407410
408411
409
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
410518
411519
412520
413521
414522
415523
416
524
525
417526
418527
419528
420529
421530
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525531
526532
527533
......
575581
576582
577583
578
584
585
579586
580587
581588
if (acpi_cpu_count > 0)
{
bool cpu_dynamic_fsb = false, cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
struct p_state initial, maximum, minimum, p_states[32];
uint8_t p_states_count;
uint8_t p_states_count = 0;
// Retrieving P-States, ported from code by superhai (c)
switch (Platform.CPU.Family) {
case 0x0F: // Intel Core (65nm)
case 0x17: // Intel Core (45nm)
case 0x1C: // Intel Atom (45nm)
{
bool cpu_dynamic_fsb = false;
if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
{
wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
delay(1);
cpu_dynamic_fsb = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
}
break;
bool cpu_noninteger_bus_ratio = (rdmsr64(MSR_IA32_PERF_STATUS) & (1ULL << 46));
initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
if (minimum.FID == 0)
{
uint64_t msr;
uint8_t i;
// Probe for lowest fid
for (i = maximum.FID; i >= 0x6; i--)
{
msr = rdmsr64(MSR_IA32_PERF_CONTROL);
wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
intel_waitforsts();
minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
delay(1);
}
msr = rdmsr64(MSR_IA32_PERF_CONTROL);
wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
intel_waitforsts();
}
if (minimum.VID == maximum.VID)
{
uint64_t msr;
uint8_t i;
// Probe for lowest vid
for (i = maximum.VID; i > 0xA; i--)
{
msr = rdmsr64(MSR_IA32_PERF_CONTROL);
wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
intel_waitforsts();
minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
delay(1);
}
msr = rdmsr64(MSR_IA32_PERF_CONTROL);
wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
intel_waitforsts();
}
minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
// Sanity check
if (maximum.CID < minimum.CID)
{
DBG("Insane FID values!");
p_states_count = 1;
}
else
{
// Finalize P-States
// Find how many P-States machine supports
p_states_count = maximum.CID - minimum.CID + 1;
if (p_states_count > 32)
p_states_count = 32;
uint8_t vidstep;
uint8_t i = 0, u, invalid = 0;
vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
for (u = 0; u < p_states_count; u++)
{
i = u - invalid;
p_states[i].CID = maximum.CID - u;
p_states[i].FID = (p_states[i].CID >> 1);
if (p_states[i].FID < 0x6)
{
if (cpu_dynamic_fsb)
p_states[i].FID = (p_states[i].FID << 1) | 0x80;
}
else if (cpu_noninteger_bus_ratio)
{
p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
}
if (i && p_states[i].FID == p_states[i-1].FID)
invalid++;
p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
uint32_t multiplier = p_states[i].FID & 0x1f;// = 0x08
bool half = p_states[i].FID & 0x40;// = 0x01
bool dfsb = p_states[i].FID & 0x80;// = 0x00
uint32_t fsb = Platform.CPU.FSBFrequency / 1000000; // = 400
uint32_t halffsb = (fsb + 1) >> 1;// = 200
uint32_t frequency = (multiplier * fsb);// = 3200
p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
}
p_states_count -= invalid;
}
} break;
case 0x1A: // Intel Core i7 LGA1366 (45nm)
case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
case 0x1F:
case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core
case 0x2F:
cpu_dynamic_fsb = rdmsr64(MSR_IA32_PERF_STATUS) & (1 << 15);
default:
verbose ("Unsupported CPU: P-States not generated !!!\n");
break;
}
}
}
initial.Control = rdmsr64(MSR_IA32_PERF_STATUS);
maximum.Control = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 32) & 0x1F3F) | (0x4000 * cpu_noninteger_bus_ratio);
maximum.CID = ((maximum.FID & 0x1F) << 1) | cpu_noninteger_bus_ratio;
minimum.FID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 24) & 0x1F) | (0x80 * cpu_dynamic_fsb);
minimum.VID = ((rdmsr64(MSR_IA32_PERF_STATUS) >> 48) & 0x3F);
if (minimum.FID == 0)
{
uint64_t msr;
uint8_t i;
// Probe for lowest fid
for (i = maximum.FID; i >= 0x6; i--)
{
msr = rdmsr64(MSR_IA32_PERF_CONTROL);
wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (i << 8) | minimum.VID);
intel_waitforsts();
minimum.FID = (rdmsr64(MSR_IA32_PERF_STATUS) >> 8) & 0x1F;
delay(1);
}
msr = rdmsr64(MSR_IA32_PERF_CONTROL);
wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
intel_waitforsts();
}
if (minimum.VID == maximum.VID)
{
uint64_t msr;
uint8_t i;
// Probe for lowest vid
for (i = maximum.VID; i > 0xA; i--)
{
msr = rdmsr64(MSR_IA32_PERF_CONTROL);
wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (minimum.FID << 8) | i);
intel_waitforsts();
minimum.VID = rdmsr64(MSR_IA32_PERF_STATUS) & 0x3F;
delay(1);
}
msr = rdmsr64(MSR_IA32_PERF_CONTROL);
wrmsr64(MSR_IA32_PERF_CONTROL, (msr & 0xFFFFFFFFFFFF0000ULL) | (maximum.FID << 8) | maximum.VID);
intel_waitforsts();
}
minimum.CID = ((minimum.FID & 0x1F) << 1) >> cpu_dynamic_fsb;
// Sanity check
if (maximum.CID < minimum.CID)
{
DBG("Insane FID values!");
p_states_count = 1;
}
else
{
// Finalize P-States
// Find how many P-States machine supports
p_states_count = maximum.CID - minimum.CID + 1;
if (p_states_count > 32)
p_states_count = 32;
uint8_t vidstep;
uint8_t i = 0, u, invalid = 0;
vidstep = ((maximum.VID << 2) - (minimum.VID << 2)) / (p_states_count - 1);
for (u = 0; u < p_states_count; u++)
{
i = u - invalid;
p_states[i].CID = maximum.CID - u;
p_states[i].FID = (p_states[i].CID >> 1);
if (p_states[i].FID < 0x6)
{
if (cpu_dynamic_fsb)
p_states[i].FID = (p_states[i].FID << 1) | 0x80;
}
else if (cpu_noninteger_bus_ratio)
{
p_states[i].FID = p_states[i].FID | (0x40 * (p_states[i].CID & 0x1));
}
if (i && p_states[i].FID == p_states[i-1].FID)
invalid++;
p_states[i].VID = ((maximum.VID << 2) - (vidstep * u)) >> 2;
uint32_t multiplier = p_states[i].FID & 0x1f;// = 0x08
bool half = p_states[i].FID & 0x40;// = 0x01
bool dfsb = p_states[i].FID & 0x80;// = 0x00
uint32_t fsb = Platform.CPU.FSBFrequency / 1000000; // = 400
uint32_t halffsb = (fsb + 1) >> 1;// = 200
uint32_t frequency = (multiplier * fsb);// = 3200
p_states[i].Frequency = (frequency + (half * halffsb)) >> dfsb;// = 3200 + 200 = 3400
}
p_states_count -= invalid;
}
// Generating SSDT
if (p_states_count > 0)
return ssdt;
}
}
else {
else
{
verbose ("ACPI CPUs not found: P-States not generated !!!\n");
}
branches/azimutz/CleanCut/i386/libsaio/smbios_patcher.c
101101
102102
103103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
104119
105120
106121
......
113128
114129
115130
116
117
118
119
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
120164
121165
122
166
123167
124168
125169
......
156200
157201
158202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
159235
160236
237
238
161239
162240
163
241
242
243
244
164245
165246
166247
......
175256
176257
177258
259
260
261
178262
179263
180264
......
291375
292376
293377
294
378
295379
296380
297381
......
493577
494578
495579
496
497
580
581
498582
583
584
499585
500586
501587
......
765851
766852
767853
768
854
855
856
857
858
769859
770860
771861
{ "",""}
};
// defaults for an iMac11,1 core i5/i7
static const SMStrEntryPair const sm_imacCore_i5_i7_defaults[]={
{"SMbiosvendor","Apple Inc."},
{"SMbiosversion","IM111.0034.B00"},
{"SMbiosdate","06/01/2009"},
{"SMmanufacter","Apple Inc."},
{"SMproductname","iMac11,1"},
{"SMsystemversion","1.0"},
{"SMserial","SOMESRLNMBR"},
{"SMfamily","iMac"},
{"SMboardmanufacter","Apple Computer, Inc."},
{"SMboardproduct","Mac-F2268DAE"},
{ "",""}
};
static const char* sm_get_defstr(const char * key, int table_num)
{
inti;
sm_defaults=sm_macbook_defaults;
}
} else {
switch (Platform.CPU.NoCores) {
case 1: sm_defaults=sm_macmini_defaults; break;
case 2: sm_defaults=sm_imac_defaults; break;
default: sm_defaults=sm_macpro_defaults; break;
switch (Platform.CPU.NoCores)
{
case 1:
sm_defaults=sm_macmini_defaults;
break;
case 2:
sm_defaults=sm_imac_defaults;
break;
default:
{
switch (Platform.CPU.Family)
{
case 0x06:
{
switch (Platform.CPU.Model)
{
case 0x19: // Intel Core i5 650
case 0x1E: // Intel Core i7 LGA1156 (45nm)
case 0x1F: // Intel Core i5 LGA1156 (45nm)
sm_defaults=sm_imacCore_i5_i7_defaults;
break;
default:
sm_defaults=sm_macpro_defaults;
break;
}
break;
}
default:
sm_defaults=sm_macpro_defaults;
break;
}
break;
}
}
}
for (i=0; sm_defaults[i].key[0]; i++) {
if (!strcmp (sm_defaults[i].key, key)) {
return sm_defaults[i].value;
return 0x0301; // Core 2 Duo
}
static int sm_get_bus_speed (const char *name, int table_num)
{
if (Platform.CPU.Vendor == 0x756E6547) // Intel
{
switch (Platform.CPU.Family)
{
case 0x06:
{
switch (Platform.CPU.Model)
{
case 0x0F: // Intel Core (65nm)
case 0x17: // Intel Core (45nm)
case 0x1C: // Intel Atom (45nm)
return 0; // TODO: populate bus speed for these processors
case 0x19: // Intel Core i5 650 @3.20 Ghz
return 3600; // GT/s / 1000
case 0x1A: // Intel Core i7 LGA1366 (45nm)
case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
case 0x1F: // Intel Core i5, i7 LGA1156 (45nm) ???
return 4800; // GT/s / 1000
case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
return 0; // TODO: populate bus speed for these processors
case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core
case 0x2E: // Intel Core i7 LGA1366 (45nm) 6 Core ???
return 0; // TODO: populate bus speed for these processors
}
}
}
}
return 0;
}
static int sm_get_cputype (const char *name, int table_num)
{
static bool done = false;
if (Platform.CPU.Vendor == 0x756E6547) // Intel
{
verbose("CPU is Intel, family 0x%x, model 0x%x, ext.model 0x%x\n", Platform.CPU.Family, Platform.CPU.Model, Platform.CPU.ExtModel);
if (!done) {
verbose("CPU is Intel, family 0x%x, model 0x%x, ext.model 0x%x\n", Platform.CPU.Family, Platform.CPU.Model, Platform.CPU.ExtModel);
done = true;
}
switch (Platform.CPU.Family)
{
case 0x1A: // Intel Core i7 LGA1366 (45nm)
return 0x0701;
case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
// get this opportunity to fill the known processor interconnect speed for cor i5/i7 in GT/s
return 0x0701;
case 0x19: // Intel Core i5 650 @3.20 Ghz
case 0x1F: // Intel Core i5, i7 LGA1156 (45nm) ???
return 0x0601;
case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
{.name="SMmemserial",.table_type=17,.value_type=SMSTRING,.offset=0x18,.auto_str=sm_get_memserial},
{.name="SMmempart",.table_type=17,.value_type=SMSTRING,.offset=0x1A,.auto_str=sm_get_mempartno},
{.name="SMcputype",.table_type=131,.value_type=SMWORD,.offset=0x04,.auto_int=sm_get_cputype},
{.name="SMbusspeed",.table_type=132,.value_type=SMWORD,.offset=0x04,.auto_str=0}
{.name="SMbusspeed",.table_type=132,.value_type=SMWORD,.offset=0x04,.auto_int=sm_get_bus_speed}
};
struct smbios_table_description smbios_table_descriptions[]=
int i, j;
int tablespresent[256];
bool do_auto=true;
extern void dumpPhysAddr(const char * title, void * a, int len);
static bool done = false; // IMPROVEME: called twice via getSmbios(), but only the second call can get all necessary info !
extern void dumpPhysAddr(const char * title, void * a, int len);
bzero(tablespresent, sizeof(tablespresent));
bzero(handles, sizeof(handles));
newsmbios->dmi.checksum = 256 - checksum8(&newsmbios->dmi, sizeof(newsmbios->dmi));
newsmbios->checksum = 0;
newsmbios->checksum = 256 - checksum8(newsmbios, sizeof(*newsmbios));
verbose("Patched DMI Table\n");
if (!done) {
verbose("Patched DMI Table\n");
done=true;
}
}
#define MAX_DMI_TABLES 96
branches/azimutz/CleanCut/i386/libsaio/memvendors.h
410410
411411
412412
413
413
414414
415415
416416
{ 3, 0x10, "Agere Systems"},
{ 3, 0x91, "NeoMagic"},
{ 3, 0x92, "AuroraNetics"},
{ 3, 0x13, "Golden Empire"},
{ 3, 0x13, "Geil"},
{ 3, 0x94, "Mushkin"},
{ 3, 0x15, "Tioga Technologies"},
{ 3, 0x16, "Netlist"},
branches/azimutz/CleanCut/i386/libsaio/dram_controllers.c
518518
519519
520520
521
522
523
524
521525
522526
523527
{ 0x8086, 0x3401, "NHM IMC",setup_nhm, get_fsb_nhm, get_timings_nhm },
{ 0x8086, 0x3402, "NHM IMC",setup_nhm, get_fsb_nhm, get_timings_nhm },
{ 0x8086, 0x3403, "NHM IMC",setup_nhm, get_fsb_nhm, get_timings_nhm },
{ 0x8086, 0x3404, "NHM IMC",setup_nhm, get_fsb_nhm, get_timings_nhm },
{ 0x8086, 0x3405, "NHM IMC",setup_nhm, get_fsb_nhm, get_timings_nhm },
{ 0x8086, 0x3406, "NHM IMC",setup_nhm, get_fsb_nhm, get_timings_nhm },
{ 0x8086, 0x3407, "NHM IMC",setup_nhm, get_fsb_nhm, get_timings_nhm },
};
branches/azimutz/CleanCut/i386/libsaio/cache.c
3939
4040
4141
42
42
4343
4444
4545
......
7474
7575
7676
77
77
7878
7979
8080
#define kCacheSize (0x100000)
#define kCacheMinBlockSize (0x200)
#define kCacheMaxBlockSize (0x4000)
#define kCacheMaxBlockSize (0x8000)
#define kCacheMaxEntries (kCacheSize / kCacheMinBlockSize)
static CICell gCacheIH;
#endif
if ((blockSize < kCacheMinBlockSize) ||
(blockSize >= kCacheMaxBlockSize))
(blockSize > kCacheMaxBlockSize))
return;
gCacheBlockSize = blockSize;
branches/azimutz/CleanCut/i386/libsaio/msdos.c
5555
5656
5757
58
5859
5960
6061
......
7475
7576
7677
78
7779
7880
7981
......
151153
152154
153155
154
156
155157
156158
157159
......
220222
221223
222224
223
224225
225
226
227
228
226229
227230
228231
229232
230233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
231249
232250
233251
......
263281
264282
265283
266
267
284
268285
269
286
270287
271
288
289
272290
273
291
274292
275293
276
277
294
278295
279296
280297
#define LABEL_LENGTH11
#define MAX_DOS_BLOCKSIZE2048
#define MAX_CACHE_BLOCKSIZE 32768
#defineCLUST_FIRST2/* reserved cluster range */
#defineCLUST_RSRVD320x0ffffff8/* reserved cluster range */
static CICell msdoscurrent = 0;
static int msdosrootcluster = 0;
static int msdosfatbits = 0;
static int msdosCacheBlockSize = 0;
#if UNUSED
/*
if (msdoscurrent == ih)
{
CacheInit(ih, msdosclustersize);
CacheInit(ih, msdosCacheBlockSize);
return 0;
}
}
msdosclustersize = msdosbps * spc;
msdoscurrent = ih;
CacheInit(ih, msdosclustersize);
msdosCacheBlockSize = (msdosclustersize > MAX_CACHE_BLOCKSIZE) ? msdosclustersize : MAX_CACHE_BLOCKSIZE;
CacheInit(ih, msdosCacheBlockSize);
free (buf);
return 0;
}
static int
readSectorAligned(CICell ih, off_t readOffset, char *buf, int size)
{
long long sectorOffset = (uint64_t)readOffset / msdosCacheBlockSize * msdosCacheBlockSize;
long relOffset = readOffset % msdosCacheBlockSize;
char *cacheBuffer;
cacheBuffer = malloc(msdosCacheBlockSize);
CacheRead(ih, cacheBuffer, sectorOffset, msdosCacheBlockSize, true);
bcopy(cacheBuffer + relOffset, buf, size);
free(cacheBuffer);
return 0;
}
static int
msdosreadcluster (CICell ih, uint8_t *buf, int size, off_t *cluster)
{
off_t readOffset;
/* Read in "cluster" */
if (buf)
{
Seek(ih, readOffset);
Read(ih, (long)buf, size);
readSectorAligned(ih, readOffset, (char *)buf, size);
}
/* Find first sector of FAT */
readOffset = msdosressector*msdosbps;
readOffset = msdosressector * msdosbps;
/* Find sector containing "cluster" entry in FAT */
readOffset += ((uint64_t)*cluster * (uint64_t)msdosfatbits)/8;
readOffset += ((uint64_t)*cluster * (uint64_t)msdosfatbits) / 8;
/* Read one sector of the FAT */
Seek(ih, readOffset);
Read(ih, (long)tmpbuf, 4);
readSectorAligned(ih, readOffset, tmpbuf, 4);
switch (msdosfatbits) {
case 32:
branches/azimutz/CleanCut/i386/libsa/memory.h
5757
5858
5959
60
60
6161
6262
6363
#define BOOT2_SEG 0x2000
#define BOOT2_OFS 0x0200 // 512 byte disk sector offset
#define BIOS_ADDR 0x9000 // BIOS disk I/O buffer
#define BIOS_ADDR 0x8000 // BIOS disk I/O buffer
#define BIOS_LEN 0x8000 // 32K - divisible by 512 and 2048
#define BOOT0_ADDR 0x7E00 // boot0 gets loaded here

Archive Download the corresponding diff file

Revision: 298