Chameleon

Chameleon Commit Details

Date:2011-06-25 18:05:07 (12 years 9 months ago)
Author:Evan Lojewski
Commit:1065
Parents: 1064
Message:Stripping out a bunch of code...
Changes:
D/branches/rewrite/i386/boot2/options.c
D/branches/rewrite/i386/boot2/graphic_utils.c
D/branches/rewrite/i386/boot2/ramdisk.h
D/branches/rewrite/i386/boot2/picopng.c
D/branches/rewrite/i386/boot2/resume.c
D/branches/rewrite/i386/boot2/graphic_utils.h
D/branches/rewrite/i386/boot2/picopng.h
D/branches/rewrite/i386/boot2/WKdm.h
D/branches/rewrite/i386/boot2/drivers.c
D/branches/rewrite/i386/boot2/bmdecompress.c
D/branches/rewrite/i386/boot2/appleClut8.h
D/branches/rewrite/i386/boot2/IOHibernatePrivate.h
D/branches/rewrite/i386/boot2/lzss.c
D/branches/rewrite/i386/boot2/graphics.h
D/branches/rewrite/i386/boot2/prompt.c
D/branches/rewrite/i386/boot2/gui.c
D/branches/rewrite/i386/boot2/WKdmDecompress.c
D/branches/rewrite/i386/boot2/gui.h
D/branches/rewrite/i386/boot2/ramdisk.c
D/branches/rewrite/i386/boot2/appleboot.h
M/branches/rewrite/i386/boot2/Makefile
M/branches/rewrite/i386/libsaio/console.c
M/branches/rewrite/i386/boot2/boot.c
M/branches/rewrite/i386/libsaio/sys.c
M/branches/rewrite/i386/libsaio/load.c
M/branches/rewrite/i386/boot2/mboot.c
M/branches/rewrite/i386/libsaio/platform.c
M/branches/rewrite/i386/libsaio/allocate.c
M/branches/rewrite/i386/libsaio/cpu.c
M/branches/rewrite/i386/libsaio/disk.c
M/branches/rewrite/i386/libsaio/Makefile
M/branches/rewrite/i386/libsaio/pci.c
M/branches/rewrite/i386/libsaio/stringTable.c
M/branches/rewrite/i386/boot2/Cconfig

File differences

branches/rewrite/i386/libsaio/console.c
4848
4949
5050
51
52
5351
5452
5553
......
173171
174172
175173
176
177
178
179
180174
175
176
181177
182178
183179
......
204200
205201
206202
207
208
209
210
203
211204
212205
213206
......
234227
235228
236229
237
238
239
240
230
241231
242232
243233
......
248238
249239
250240
251
252
253
254
255
241
256242
257243
258244
#include "bootstruct.h"
#include <vers.h>
extern intvprf(const char * fmt, va_list ap);
bool gVerboseMode;
bool gErrors;
{
va_list ap;
va_start(ap, fmt);
if (bootArgs->Video.v_display == VGA_TEXT_MODE)
prf(fmt, ap, putchar, 0);
else
vprf(fmt, ap);
prf(fmt, ap, putchar, 0);
{
// Kabyl: BooterLog
struct putc_info pi;
va_start(ap, fmt);
if (gVerboseMode)
{
if (bootArgs->Video.v_display == VGA_TEXT_MODE)
prf(fmt, ap, putchar, 0);
else
vprf(fmt, ap);
prf(fmt, ap, putchar, 0);
}
{
va_list ap;
gErrors = true;
va_start(ap, fmt);
if (bootArgs->Video.v_display == VGA_TEXT_MODE)
prf(fmt, ap, putchar, 0);
else
vprf(fmt, ap);
prf(fmt, ap, putchar, 0);
va_end(ap);
return(0);
}
printf("\n");
va_start(ap, fmt);
if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
prf(fmt, ap, putchar, 0);
} else {
vprf(fmt, ap);
}
prf(fmt, ap, putchar, 0);
va_end(ap);
printf("\nThis is a non recoverable error! System HALTED!!!");
halt();
branches/rewrite/i386/libsaio/allocate.c
2727
2828
2929
30
31
3230
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
31
#include "bootstruct.h"
#include "device_tree.h"
static long gImageLastKernelAddr;
#define kPageSize 4096
#define RoundPage(x) ((((unsigned)(x)) + kPageSize - 1) & ~(kPageSize - 1))
long
AllocateMemoryRange(char * rangeName, long start, long length, long type)
{
char *nameBuf;
uint32_t *buffer;
nameBuf = malloc(strlen(rangeName) + 1);
if (nameBuf == 0) return -1;
strcpy(nameBuf, rangeName);
buffer = malloc(2 * sizeof(uint32_t));
if (buffer == 0) return -1;
buffer[0] = start;
buffer[1] = length;
DT__AddProperty(gMemoryMapNode, nameBuf, 2 * sizeof(uint32_t), (char *)buffer);
return 0;
}
long
AllocateKernelMemory( long inSize )
{
long addr;
if (gImageLastKernelAddr == 0) {
gImageLastKernelAddr = RoundPage( bootArgs->kaddr +
bootArgs->ksize );
}
addr = gImageLastKernelAddr;
gImageLastKernelAddr += RoundPage(inSize);
if ( gImageLastKernelAddr >= (KERNEL_ADDR + KERNEL_LEN) ) {
stop ("AllocateKernelMemory error");
}
bootArgs->ksize = gImageLastKernelAddr - bootArgs->kaddr;
return addr;
}
#define RoundPage(x) ((((unsigned)(x)) + kPageSize - 1) & ~(kPageSize - 1))
branches/rewrite/i386/libsaio/Makefile
2929
3030
3131
32
33
32
33
3434
3535
3636
37
38
39
40
41
37
38
39
40
41
4242
43
43
4444
4545
4646
INC = -I. -I$(SYMROOT) -I$(LIBSADIR) -I$(BOOT2DIR) -I${SRCROOT}/i386/include
SAIO_OBJS = table.o asm.o bios.o biosfn.o \
disk.o sys.o cache.o bootstruct.o \
stringTable.o load.o pci.o allocate.o misc.o \
disk.o sys.o cache.o \
stringTable.o allocate.o misc.o \
ufs.o ufs_byteorder.o \
vbe.o nbp.o hfs.o hfs_compare.o \
xml.o ntfs.o msdos.o md5c.o device_tree.o \
cpu.o platform.o acpi_patcher.o \
smbios.o smbios_getters.o smbios_decode.o \
fake_efi.o ext2fs.o \
hpet.o dram_controllers.o spd.o usb.o pci_setup.o \
device_inject.o nvidia.o ati.o pci_root.o \
cpu.o platform.o pci.o \
\
ext2fs.o \
hpet.o dram_controllers.o spd.o \
load.o\
convert.o aml_generator.o console.o
#OLD: acpi_patcher.o fake_efi.o smbios.o smbios_getters.o smbios_decode.o pci_setup.o pci_root.o device_inject.o bootstruct.o nvidia.o ati.o usb.o
LIBS = libsaio.a
LIBS := $(addprefix $(SYMROOT)/, $(LIBS))
branches/rewrite/i386/libsaio/sys.c
6363
6464
6565
66
6766
6867
6968
......
816815
817816
818817
819
818
820819
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837820
838821
839822
......
10251008
10261009
10271010
1028
1029
10301011
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
10431012
10441013
10451014
#include "boot.h"
#include "bootstruct.h"
#include "disk.h"
#include "ramdisk.h"
#include "xml.h"
#include <libkern/crypto/md5.h>
for ( bvr = chain; bvr; bvr = bvr->next )
if ( bvr->part_no == multiboot_partition && bvr->biosdev == gBIOSDev )
return bvr;
/*
* 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.
*/
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);
}
/*
* 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
bvr = bvr1 = NULL;
// Try resolving "rd" and "bt" devices first.
if (biosdev == kPseudoBIOSDevRAMDisk)
{
if (gRAMDiskVolume)
bvr1 = gRAMDiskVolume;
}
else if (biosdev == kPseudoBIOSDevBooter)
{
if (gRAMDiskVolume != NULL && gRAMDiskBTAliased)
bvr1 = gRAMDiskVolume;
else
bvr1 = gBIOSBootVolume;
}
else
{
// Fetch the volume list from the device.
scanBootVolumes( biosdev, NULL );
branches/rewrite/i386/libsaio/load.c
324324
325325
326326
327
327
328328
329
329
330330
331331
332332
totalSize = symsSize + symTab->strsize;
gSymbolTableSize = totalSize + sizeof(struct symtab_command);
gSymbolTableAddr = AllocateKernelMemory(gSymbolTableSize);
// gSymbolTableAddr = AllocateKernelMemory(gSymbolTableSize);
// Add the SymTab to the memory-map.
AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize, -1);
// AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize, -1);
symTableSave = (struct symtab_command *)gSymbolTableAddr;
tmpAddr = gSymbolTableAddr + sizeof(struct symtab_command);
branches/rewrite/i386/libsaio/platform.c
3636
3737
3838
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
6139
6240
6341
......
6745
6846
6947
70
7148
}
}
/** scan mem for memory autodection purpose */
void scan_mem() {
static bool done = false;
if (done) return;
/* our code only works on Intel chipsets so make sure here */
if (pci_config_read16(PCIADDR(0, 0x00, 0), 0x00) != 0x8086)
bootInfo->memDetect = false;
else
bootInfo->memDetect = true;
/* manually */
getBoolForKey(kUseMemDetect, &bootInfo->memDetect, &bootInfo->bootConfig);
if (bootInfo->memDetect) {
if (dram_controller_dev != NULL) {
scan_dram_controller(dram_controller_dev); // Rek: pci dev ram controller direct and fully informative scan ...
}
scan_spd(&Platform);
}
done = true;
}
/**
Scan platform hardware information, called by the main entry point (common_boot() )
_before_ bootConfig xml parsing settings are loaded
memset(&Platform, 0, sizeof(Platform));
build_pci_dt();
scan_cpu(&Platform);
//scan_mem(); Rek: called after pci devs init in fake_efi now ...
}
branches/rewrite/i386/libsaio/cpu.c
9797
9898
9999
100
101
100
102101
103102
104103
......
266265
267266
268267
269
270
271
272
273268
274
275
276
277
278
279
280
281
282
283
284
285269
286270
287271
uint64_ttscFrequency, fsbFrequency, cpuFrequency;
uint64_tmsr, flex_ratio;
uint8_tmaxcoef, maxdiv, currcoef, bus_ratio_max, currdiv;
const char *newratio;
int len, myfsb;
int myfsb;
uint8_t bus_ratio_min;
uint32_t max_ratio, min_ratio;
} else {
cpuFrequency = tscFrequency;
}
if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->bootConfig)) && (len <= 4)) {
max_ratio = atoi(newratio);
max_ratio = (max_ratio * 10);
if (len >= 3) max_ratio = (max_ratio + 5);
verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio);
// extreme overclockers may love 320 ;)
if ((max_ratio >= min_ratio) && (max_ratio <= 320)) {
cpuFrequency = (fsbFrequency * max_ratio) / 10;
if (len >= 3) maxdiv = 1;
else maxdiv = 0;
} else {
max_ratio = (bus_ratio_max * 10);
}
}
//valv: to be uncommented if Remarq.1 didn't stick
/*if(bus_ratio_max > 0) bus_ratio = flex_ratio;*/
p->CPU.MaxRatio = max_ratio;
branches/rewrite/i386/libsaio/disk.c
129129
130130
131131
132
133
134132
135133
136134
......
335333
336334
337335
338
339
340336
341337
342338
......
15631559
15641560
15651561
1566
1567
1568
1569
15701562
1571
1572
1573
1574
1575
1576
15771563
15781564
15791565
......
16061592
16071593
16081594
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
16271595
16281596
16291597
......
16511619
16521620
16531621
1654
16551622
16561623
16571624
......
17351702
17361703
17371704
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
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
17901705
17911706
17921707
......
18091724
18101725
18111726
1812
1813
1814
1815
1816
1817
18181727
18191728
18201729
......
19551864
19561865
19571866
1958
19591867
19601868
19611869
......
19911899
19921900
19931901
1994
19951902
19961903
19971904
int (*p_get_ramdisk_info)(int biosdev, struct driveInfo *dip) = NULL;
extern void spinActivityIndicator(int sectors);
//==========================================================================
static int getDriveInfo( int biosdev, struct driveInfo *dip )
biosbuf = trackbuf + (secno % divisor) * BPS;
xbiosdev = biosdev;
spinActivityIndicator(xnsecs);
return rc;
}
struct DiskBVMap * map = NULL;
int bvCount = 0;
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
* individual bvr chains of each drive.
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) )
{
char *start, *next = val;
long len = 0;
do
{
start = strbreak(next, &next, &len);
if(len && matchVolumeToString(newBVR, start, len) )
newBVR->visible = false;
}
while ( next && *next );
}
/*
* Use the first bvr entry as the starting chain pointer.
*/
if (!chain)
*count = bvCount;
free(val);
return chain;
}
return false;
}
/* If Rename Partition has defined an alias, then extract it for description purpose.
* The format for the rename string is the following:
* hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" "alias"; etc...
*/
bool getVolumeLabelAlias(BVRef bvr, char* str, long strMaxLen)
{
char *aliasList, *entryStart, *entryNext;
if ( !str || strMaxLen <= 0)
return false;
aliasList = XMLDecode(getStringForKey(kRenamePartition, &bootInfo->bootConfig));
if ( !aliasList )
return false;
for ( entryStart = entryNext = aliasList;
entryNext && *entryNext;
entryStart = entryNext )
{
char *volStart, *volEnd, *aliasStart;
long volLen, aliasLen;
// Delimit current entry
entryNext = strchr(entryStart, ';');
if ( entryNext )
{
*entryNext = '\0';
entryNext++;
}
volStart = strbreak(entryStart, &volEnd, &volLen);
if(!volLen)
continue;
aliasStart = strbreak(volEnd, 0, &aliasLen);
if(!aliasLen)
continue;
if ( matchVolumeToString(bvr, volStart, volLen) )
{
strncat(str, aliasStart, MIN(strMaxLen, aliasLen));
free(aliasList);
return true;
}
}
free(aliasList);
return false;
}
void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen, bool useDeviceDescription )
{
unsigned char type;
p += len;
}
/* See if a partition rename is preferred */
if(getVolumeLabelAlias(bvr, p, strMaxLen)) {
strncpy(bvr->label, p, 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.
len -= copy_len;
cbuf += copy_len;
secno += secs;
spinActivityIndicator(secs);
}
return 0;
len -= copy_len;
cbuf += copy_len;
secno += secs;
spinActivityIndicator(secs);
}
return 0;
branches/rewrite/i386/libsaio/pci.c
152152
153153
154154
155
155
156156
157157
158158
dev_path[0] = 0;
end = root_pci_dev;
int uid = getPciRootUID();
int uid = 0; //getPciRootUID();
while (end != pci_dt)
{
current = pci_dt;
branches/rewrite/i386/libsaio/stringTable.c
481481
482482
483483
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
484
519485
520486
521487
bool getValueForKey( const char *key, const char **val, int *size, config_file_t *config )
{
const char *overrideVal;
int overrideSize;
bool override, ret;
if (getValueForBootKey(bootArgs->CommandLine, key, val, size))
return true;
ret = getValueForConfigTableKey(config, key, val, size);
// Try to find alternate keys in bootInfo->overrideConfig
// and prefer its values with the exceptions for
// "Kernel"="mach_kernel" and "Kernel Flags"="".
if (config->canOverride)
{
if (getValueForConfigTableKey(&bootInfo->overrideConfig, key, &overrideVal, &overrideSize))
{
override = true;
if (ret && (strcmp(key, "Kernel") == 0) && (strcmp(overrideVal, "mach_kernel") == 0))
override = false;
if (ret && (strcmp(key, "Kernel Flags") == 0) && (overrideSize == 0))
override = false;
if (override)
{
*val = overrideVal;
*size = overrideSize;
return true;
}
}
}
return ret;
return getValueForConfigTableKey(config, key, val, size);
}
branches/rewrite/i386/boot2/ramdisk.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
* Supplemental ramdisk functions for the multiboot ramdisk driver
* Copyright 2009 Tamas Kosarszky. All rights reserved.
*
*/
#ifndef __BOOT_RAMDISK_H
#define __BOOT_RAMDISK_H
#define RAMDISKCONFIG_FILENAME "rd(0,0)/RAMDisk.plist"
//#define kPostbootRamdisk
void md0Ramdisk();
typedef struct RAMDiskParam
{
ppnum_t base;
unsigned int size;
} RAMDiskParam;
/* mboot.c */
extern struct multiboot_info *gMI;
extern int multibootRamdiskReadBytes( int biosdev, unsigned int blkno,
unsigned int byteoff,
unsigned int byteCount, void * buffer );
extern int multiboot_get_ramdisk_info(int biosdev, struct driveInfo *dip);
//
extern BVRef gRAMDiskVolume;
extern bool gRAMDiskBTAliased;
extern void setRAMDiskBTHook(bool mode);
extern int mountRAMDisk(const char * param);
extern void processRAMDiskCommand(char ** argPtr, const char * cmd);
extern int loadPrebootRAMDisk();
#endif /* !__BOOT_RAMDISK_H */
branches/rewrite/i386/boot2/picopng.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
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
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
// picoPNG version 20080503 (cleaned up and ported to c by kaitek)
// Copyright (c) 2005-2008 Lode Vandevenne
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
#include <sys/types.h>
#include "libsa.h"
#include "picopng.h"
/*************************************************************************************************/
typedef struct png_alloc_node {
struct png_alloc_node *prev, *next;
void *addr;
size_t size;
} png_alloc_node_t;
png_alloc_node_t *png_alloc_head = NULL;
png_alloc_node_t *png_alloc_tail = NULL;
png_alloc_node_t *png_alloc_find_node(void *addr)
{
png_alloc_node_t *node;
for (node = png_alloc_head; node; node = node->next)
if (node->addr == addr)
break;
return node;
}
void png_alloc_add_node(void *addr, size_t size)
{
png_alloc_node_t *node;
if (png_alloc_find_node(addr))
return;
node = malloc(sizeof (png_alloc_node_t));
node->addr = addr;
node->size = size;
node->prev = png_alloc_tail;
node->next = NULL;
png_alloc_tail = node;
if (node->prev)
node->prev->next = node;
if (!png_alloc_head)
png_alloc_head = node;
}
void png_alloc_remove_node(png_alloc_node_t *node)
{
if (node->prev)
node->prev->next = node->next;
if (node->next)
node->next->prev = node->prev;
if (node == png_alloc_head)
png_alloc_head = node->next;
if (node == png_alloc_tail)
png_alloc_tail = node->prev;
node->prev = node->next = node->addr = NULL;
free(node);
}
void *png_alloc_malloc(size_t size)
{
void *addr = malloc(size);
png_alloc_add_node(addr, size);
return addr;
}
void *png_alloc_realloc(void *addr, size_t size)
{
void *new_addr;
if (!addr)
return png_alloc_malloc(size);
new_addr = realloc(addr, size);
if (new_addr != addr) {
png_alloc_node_t *old_node;
old_node = png_alloc_find_node(addr);
png_alloc_remove_node(old_node);
png_alloc_add_node(new_addr, size);
}
return new_addr;
}
void png_alloc_free(void *addr)
{
png_alloc_node_t *node = png_alloc_find_node(addr);
if (!node)
return;
png_alloc_remove_node(node);
free(addr);
}
void png_alloc_free_all()
{
while (png_alloc_tail) {
void *addr = png_alloc_tail->addr;
png_alloc_remove_node(png_alloc_tail);
free(addr);
}
}
/*************************************************************************************************/
__unused void vector32_cleanup(vector32_t *p)
{
p->size = p->allocsize = 0;
if (p->data)
png_alloc_free(p->data);
p->data = NULL;
}
uint32_t vector32_resize(vector32_t *p, size_t size)
{// returns 1 if success, 0 if failure ==> nothing done
if (size * sizeof (uint32_t) > p->allocsize) {
size_t newsize = size * sizeof (uint32_t) * 2;
void *data = png_alloc_realloc(p->data, newsize);
if (data) {
p->allocsize = newsize;
p->data = (uint32_t *) data;
p->size = size;
} else
return 0;
} else
p->size = size;
return 1;
}
uint32_t vector32_resizev(vector32_t *p, size_t size, uint32_t value)
{// resize and give all new elements the value
size_t oldsize = p->size, i;
if (!vector32_resize(p, size))
return 0;
for (i = oldsize; i < size; i++)
p->data[i] = value;
return 1;
}
void vector32_init(vector32_t *p)
{
p->data = NULL;
p->size = p->allocsize = 0;
}
vector32_t *vector32_new(size_t size, uint32_t value)
{
vector32_t *p = png_alloc_malloc(sizeof (vector32_t));
vector32_init(p);
if (size && !vector32_resizev(p, size, value))
return NULL;
return p;
}
/*************************************************************************************************/
__unused void vector8_cleanup(vector8_t *p)
{
p->size = p->allocsize = 0;
if (p->data)
png_alloc_free(p->data);
p->data = NULL;
}
uint32_t vector8_resize(vector8_t *p, size_t size)
{// returns 1 if success, 0 if failure ==> nothing done
// xxx: the use of sizeof uint32_t here seems like a bug (this descends from the lodepng vector
// compatibility functions which do the same). without this there is corruption in certain cases,
// so this was probably done to cover up allocation bug(s) in the original picopng code!
if (size * sizeof (uint32_t) > p->allocsize) {
size_t newsize = size * sizeof (uint32_t) * 2;
void *data = png_alloc_realloc(p->data, newsize);
if (data) {
p->allocsize = newsize;
p->data = (uint8_t *) data;
p->size = size;
} else
return 0; // error: not enough memory
} else
p->size = size;
return 1;
}
uint32_t vector8_resizev(vector8_t *p, size_t size, uint8_t value)
{// resize and give all new elements the value
size_t oldsize = p->size, i;
if (!vector8_resize(p, size))
return 0;
for (i = oldsize; i < size; i++)
p->data[i] = value;
return 1;
}
void vector8_init(vector8_t *p)
{
p->data = NULL;
p->size = p->allocsize = 0;
}
vector8_t *vector8_new(size_t size, uint8_t value)
{
vector8_t *p = png_alloc_malloc(sizeof (vector8_t));
vector8_init(p);
if (size && !vector8_resizev(p, size, value))
return NULL;
return p;
}
vector8_t *vector8_copy(vector8_t *p)
{
vector8_t *q = vector8_new(p->size, 0);
uint32_t n;
for (n = 0; n < q->size; n++)
q->data[n] = p->data[n];
return q;
}
/*************************************************************************************************/
const uint32_t LENBASE[29] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51,
59, 67, 83, 99, 115, 131, 163, 195, 227, 258 };
const uint32_t LENEXTRA[29] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
4, 5, 5, 5, 5, 0 };
const uint32_t DISTBASE[30] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 };
const uint32_t DISTEXTRA[30] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
10, 10, 11, 11, 12, 12, 13, 13 };
// code length code lengths
const uint32_t CLCL[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
/*************************************************************************************************/
typedef struct {
// 2D representation of a huffman tree: The one dimension is "0" or "1", the other contains all
// nodes and leaves of the tree.
vector32_t *tree2d;
} HuffmanTree;
HuffmanTree *HuffmanTree_new()
{
HuffmanTree *tree = png_alloc_malloc(sizeof (HuffmanTree));
tree->tree2d = NULL;
return tree;
}
int HuffmanTree_makeFromLengths(HuffmanTree *tree, const vector32_t *bitlen, uint32_t maxbitlen)
{// make tree given the lengths
uint32_t bits, n, i;
uint32_t numcodes = (uint32_t) bitlen->size, treepos = 0, nodefilled = 0;
vector32_t *tree1d, *blcount, *nextcode;
tree1d = vector32_new(numcodes, 0);
blcount = vector32_new(maxbitlen + 1, 0);
nextcode = vector32_new(maxbitlen + 1, 0);
for (bits = 0; bits < numcodes; bits++)
blcount->data[bitlen->data[bits]]++; // count number of instances of each code length
for (bits = 1; bits <= maxbitlen; bits++)
nextcode->data[bits] = (nextcode->data[bits - 1] + blcount->data[bits - 1]) << 1;
for (n = 0; n < numcodes; n++)
if (bitlen->data[n] != 0)
tree1d->data[n] = nextcode->data[bitlen->data[n]]++; // generate all the codes
// 0x7fff here means the tree2d isn't filled there yet
vector32_t *tree2d = vector32_new(numcodes * 2, 0x7fff);
tree->tree2d = tree2d;
for (n = 0; n < numcodes; n++) // the codes
for (i = 0; i < bitlen->data[n]; i++) { // the bits for this code
uint32_t bit = (tree1d->data[n] >> (bitlen->data[n] - i - 1)) & 1;
if (treepos > numcodes - 2)
return 55;
if (tree2d->data[2 * treepos + bit] == 0x7fff) { // not yet filled in
if (i + 1 == bitlen->data[n]) { // last bit
tree2d->data[2 * treepos + bit] = n;
treepos = 0;
} else { // addresses are encoded as values > numcodes
tree2d->data[2 * treepos + bit] = ++nodefilled + numcodes;
treepos = nodefilled;
}
} else // subtract numcodes from address to get address value
treepos = tree2d->data[2 * treepos + bit] - numcodes;
}
return 0;
}
int HuffmanTree_decode(const HuffmanTree *tree, bool *decoded, uint32_t *result, size_t *treepos,
uint32_t bit)
{// Decodes a symbol from the tree
const vector32_t *tree2d = tree->tree2d;
uint32_t numcodes = (uint32_t) tree2d->size / 2;
if (*treepos >= numcodes)
return 11; // error: you appeared outside the codetree
*result = tree2d->data[2 * (*treepos) + bit];
*decoded = (*result < numcodes);
*treepos = *decoded ? 0 : *result - numcodes;
return 0;
}
/*************************************************************************************************/
int Inflator_error;
uint32_t Zlib_readBitFromStream(size_t *bitp, const uint8_t *bits)
{
uint32_t result = (bits[*bitp >> 3] >> (*bitp & 0x7)) & 1;
(*bitp)++;
return result;
}
uint32_t Zlib_readBitsFromStream(size_t *bitp, const uint8_t *bits, size_t nbits)
{
uint32_t i, result = 0;
for (i = 0; i < nbits; i++)
result += (Zlib_readBitFromStream(bitp, bits)) << i;
return result;
}
void Inflator_generateFixedTrees(HuffmanTree *tree, HuffmanTree *treeD)
{// get the tree of a deflated block with fixed tree
size_t i;
vector32_t *bitlen, *bitlenD;
bitlen = vector32_new(288, 8);
bitlenD = vector32_new(32, 5);
for (i = 144; i <= 255; i++)
bitlen->data[i] = 9;
for (i = 256; i <= 279; i++)
bitlen->data[i] = 7;
HuffmanTree_makeFromLengths(tree, bitlen, 15);
HuffmanTree_makeFromLengths(treeD, bitlenD, 15);
}
uint32_t Inflator_huffmanDecodeSymbol(const uint8_t *in, size_t *bp, const HuffmanTree *codetree,
size_t inlength)
{// decode a single symbol from given list of bits with given code tree. returns the symbol
bool decoded = false;
uint32_t ct = 0;
size_t treepos = 0;
for (;;) {
if ((*bp & 0x07) == 0 && (*bp >> 3) > inlength) {
Inflator_error = 10; // error: end reached without endcode
return 0;
}
Inflator_error = HuffmanTree_decode(codetree, &decoded, &ct, &treepos,
Zlib_readBitFromStream(bp, in));
if (Inflator_error)
return 0; // stop, an error happened
if (decoded)
return ct;
}
}
void Inflator_getTreeInflateDynamic(HuffmanTree *tree, HuffmanTree *treeD, const uint8_t *in,
size_t *bp, size_t inlength)
{// get the tree of a deflated block with dynamic tree, the tree itself is also Huffman
// compressed with a known tree
size_t i, n;
HuffmanTree *codelengthcodetree = HuffmanTree_new(); // the code tree for code length codes
vector32_t *bitlen, *bitlenD;
bitlen = vector32_new(288, 0);
bitlenD = vector32_new(32, 0);
if (*bp >> 3 >= inlength - 2) {
Inflator_error = 49; // the bit pointer is or will go past the memory
return;
}
size_t HLIT = Zlib_readBitsFromStream(bp, in, 5) + 257;// number of literal/length codes + 257
size_t HDIST = Zlib_readBitsFromStream(bp, in, 5) + 1;// number of dist codes + 1
size_t HCLEN = Zlib_readBitsFromStream(bp, in, 4) + 4;// number of code length codes + 4
vector32_t *codelengthcode; // lengths of tree to decode the lengths of the dynamic tree
codelengthcode = vector32_new(19, 0);
for (i = 0; i < 19; i++)
codelengthcode->data[CLCL[i]] = (i < HCLEN) ? Zlib_readBitsFromStream(bp, in, 3) : 0;
Inflator_error = HuffmanTree_makeFromLengths(codelengthcodetree, codelengthcode, 7);
if (Inflator_error)
return;
size_t replength;
for (i = 0; i < HLIT + HDIST; ) {
uint32_t code = Inflator_huffmanDecodeSymbol(in, bp, codelengthcodetree, inlength);
if (Inflator_error)
return;
if (code <= 15) { // a length code
if (i < HLIT)
bitlen->data[i++] = code;
else
bitlenD->data[i++ - HLIT] = code;
} else if (code == 16) { // repeat previous
if (*bp >> 3 >= inlength) {
Inflator_error = 50; // error, bit pointer jumps past memory
return;
}
replength = 3 + Zlib_readBitsFromStream(bp, in, 2);
uint32_t value; // set value to the previous code
if ((i - 1) < HLIT)
value = bitlen->data[i - 1];
else
value = bitlenD->data[i - HLIT - 1];
for (n = 0; n < replength; n++) { // repeat this value in the next lengths
if (i >= HLIT + HDIST) {
Inflator_error = 13; // error: i is larger than the amount of codes
return;
}
if (i < HLIT)
bitlen->data[i++] = value;
else
bitlenD->data[i++ - HLIT] = value;
}
} else if (code == 17) { // repeat "0" 3-10 times
if (*bp >> 3 >= inlength) {
Inflator_error = 50; // error, bit pointer jumps past memory
return;
}
replength = 3 + Zlib_readBitsFromStream(bp, in, 3);
for (n = 0; n < replength; n++) { // repeat this value in the next lengths
if (i >= HLIT + HDIST) {
Inflator_error = 14; // error: i is larger than the amount of codes
return;
}
if (i < HLIT)
bitlen->data[i++] = 0;
else
bitlenD->data[i++ - HLIT] = 0;
}
} else if (code == 18) { // repeat "0" 11-138 times
if (*bp >> 3 >= inlength) {
Inflator_error = 50; // error, bit pointer jumps past memory
return;
}
replength = 11 + Zlib_readBitsFromStream(bp, in, 7);
for (n = 0; n < replength; n++) { // repeat this value in the next lengths
if (i >= HLIT + HDIST) {
Inflator_error = 15; // error: i is larger than the amount of codes
return;
}
if (i < HLIT)
bitlen->data[i++] = 0;
else
bitlenD->data[i++ - HLIT] = 0;
}
} else {
Inflator_error = 16; // error: an nonexitent code appeared. This can never happen.
return;
}
}
if (bitlen->data[256] == 0) {
Inflator_error = 64; // the length of the end code 256 must be larger than 0
return;
}
// now we've finally got HLIT and HDIST, so generate the code trees, and the function is done
Inflator_error = HuffmanTree_makeFromLengths(tree, bitlen, 15);
if (Inflator_error)
return;
Inflator_error = HuffmanTree_makeFromLengths(treeD, bitlenD, 15);
if (Inflator_error)
return;
}
void Inflator_inflateHuffmanBlock(vector8_t *out, const uint8_t *in, size_t *bp, size_t *pos,
size_t inlength, uint32_t btype)
{
HuffmanTree *codetree, *codetreeD; // the code tree for Huffman codes, dist codes
codetree = HuffmanTree_new();
codetreeD = HuffmanTree_new();
if (btype == 1)
Inflator_generateFixedTrees(codetree, codetreeD);
else if (btype == 2) {
Inflator_getTreeInflateDynamic(codetree, codetreeD, in, bp, inlength);
if (Inflator_error)
return;
}
for (;;) {
uint32_t code = Inflator_huffmanDecodeSymbol(in, bp, codetree, inlength);
if (Inflator_error)
return;
if (code == 256) // end code
return;
else if (code <= 255) { // literal symbol
if (*pos >= out->size)
vector8_resize(out, (*pos + 1) * 2); // reserve more room
out->data[(*pos)++] = (uint8_t) code;
} else if (code >= 257 && code <= 285) { // length code
size_t length = LENBASE[code - 257], numextrabits = LENEXTRA[code - 257];
if ((*bp >> 3) >= inlength) {
Inflator_error = 51; // error, bit pointer will jump past memory
return;
}
length += Zlib_readBitsFromStream(bp, in, numextrabits);
uint32_t codeD = Inflator_huffmanDecodeSymbol(in, bp, codetreeD, inlength);
if (Inflator_error)
return;
if (codeD > 29) {
Inflator_error = 18; // error: invalid dist code (30-31 are never used)
return;
}
uint32_t dist = DISTBASE[codeD], numextrabitsD = DISTEXTRA[codeD];
if ((*bp >> 3) >= inlength) {
Inflator_error = 51; // error, bit pointer will jump past memory
return;
}
dist += Zlib_readBitsFromStream(bp, in, numextrabitsD);
size_t start = *pos, back = start - dist; // backwards
if (*pos + length >= out->size)
vector8_resize(out, (*pos + length) * 2); // reserve more room
size_t i;
for (i = 0; i < length; i++) {
out->data[(*pos)++] = out->data[back++];
if (back >= start)
back = start - dist;
}
}
}
}
void Inflator_inflateNoCompression(vector8_t *out, const uint8_t *in, size_t *bp, size_t *pos,
size_t inlength)
{
while ((*bp & 0x7) != 0)
(*bp)++; // go to first boundary of byte
size_t p = *bp / 8;
if (p >= inlength - 4) {
Inflator_error = 52; // error, bit pointer will jump past memory
return;
}
uint32_t LEN = in[p] + 256 * in[p + 1], NLEN = in[p + 2] + 256 * in[p + 3];
p += 4;
if (LEN + NLEN != 65535) {
Inflator_error = 21; // error: NLEN is not one's complement of LEN
return;
}
if (*pos + LEN >= out->size)
vector8_resize(out, *pos + LEN);
if (p + LEN > inlength) {
Inflator_error = 23; // error: reading outside of in buffer
return;
}
uint32_t n;
for (n = 0; n < LEN; n++)
out->data[(*pos)++] = in[p++]; // read LEN bytes of literal data
*bp = p * 8;
}
void Inflator_inflate(vector8_t *out, const vector8_t *in, size_t inpos)
{
size_t bp = 0, pos = 0; // bit pointer and byte pointer
Inflator_error = 0;
uint32_t BFINAL = 0;
while (!BFINAL && !Inflator_error) {
if (bp >> 3 >= in->size) {
Inflator_error = 52; // error, bit pointer will jump past memory
return;
}
BFINAL = Zlib_readBitFromStream(&bp, &in->data[inpos]);
uint32_t BTYPE = Zlib_readBitFromStream(&bp, &in->data[inpos]);
BTYPE += 2 * Zlib_readBitFromStream(&bp, &in->data[inpos]);
if (BTYPE == 3) {
Inflator_error = 20; // error: invalid BTYPE
return;
}
else if (BTYPE == 0)
Inflator_inflateNoCompression(out, &in->data[inpos], &bp, &pos, in->size);
else
Inflator_inflateHuffmanBlock(out, &in->data[inpos], &bp, &pos, in->size, BTYPE);
}
if (!Inflator_error)
vector8_resize(out, pos); // Only now we know the true size of out, resize it to that
}
/*************************************************************************************************/
int Zlib_decompress(vector8_t *out, const vector8_t *in) // returns error value
{
if (in->size < 2)
return 53; // error, size of zlib data too small
if ((in->data[0] * 256 + in->data[1]) % 31 != 0)
// error: 256 * in->data[0] + in->data[1] must be a multiple of 31, the FCHECK value is
// supposed to be made that way
return 24;
uint32_t CM = in->data[0] & 15, CINFO = (in->data[0] >> 4) & 15, FDICT = (in->data[1] >> 5) & 1;
if (CM != 8 || CINFO > 7)
// error: only compression method 8: inflate with sliding window of 32k is supported by
// the PNG spec
return 25;
if (FDICT != 0)
// error: the specification of PNG says about the zlib stream: "The additional flags shall
// not specify a preset dictionary."
return 26;
Inflator_inflate(out, in, 2);
return Inflator_error; // note: adler32 checksum was skipped and ignored
}
/*************************************************************************************************/
#define PNG_SIGNATURE0x0a1a0a0d474e5089ull
#define CHUNK_IHDR0x52444849
#define CHUNK_IDAT0x54414449
#define CHUNK_IEND0x444e4549
#define CHUNK_PLTE0x45544c50
#define CHUNK_tRNS0x534e5274
int PNG_error;
uint32_t PNG_readBitFromReversedStream(size_t *bitp, const uint8_t *bits)
{
uint32_t result = (bits[*bitp >> 3] >> (7 - (*bitp & 0x7))) & 1;
(*bitp)++;
return result;
}
uint32_t PNG_readBitsFromReversedStream(size_t *bitp, const uint8_t *bits, uint32_t nbits)
{
uint32_t i, result = 0;
for (i = nbits - 1; i < nbits; i--)
result += ((PNG_readBitFromReversedStream(bitp, bits)) << i);
return result;
}
void PNG_setBitOfReversedStream(size_t *bitp, uint8_t *bits, uint32_t bit)
{
bits[*bitp >> 3] |= (bit << (7 - (*bitp & 0x7)));
(*bitp)++;
}
uint32_t PNG_read32bitInt(const uint8_t *buffer)
{
return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
}
int PNG_checkColorValidity(uint32_t colorType, uint32_t bd) // return type is a LodePNG error code
{
if ((colorType == 2 || colorType == 4 || colorType == 6)) {
if (!(bd == 8 || bd == 16))
return 37;
else
return 0;
} else if (colorType == 0) {
if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16))
return 37;
else
return 0;
} else if (colorType == 3) {
if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8))
return 37;
else
return 0;
} else
return 31; // nonexistent color type
}
uint32_t PNG_getBpp(const PNG_info_t *info)
{
uint32_t bitDepth, colorType;
bitDepth = info->bitDepth;
colorType = info->colorType;
if (colorType == 2)
return (3 * bitDepth);
else if (colorType >= 4)
return (colorType - 2) * bitDepth;
else
return bitDepth;
}
void PNG_readPngHeader(PNG_info_t *info, const uint8_t *in, size_t inlength)
{// read the information from the header and store it in the Info
if (inlength < 29) {
PNG_error = 27; // error: the data length is smaller than the length of the header
return;
}
if (*(uint64_t *) in != PNG_SIGNATURE) {
PNG_error = 28; // no PNG signature
return;
}
if (*(uint32_t *) &in[12] != CHUNK_IHDR) {
PNG_error = 29; // error: it doesn't start with a IHDR chunk!
return;
}
info->width = PNG_read32bitInt(&in[16]);
info->height = PNG_read32bitInt(&in[20]);
info->bitDepth = in[24];
info->colorType = in[25];
info->compressionMethod = in[26];
if (in[26] != 0) {
PNG_error = 32; // error: only compression method 0 is allowed in the specification
return;
}
info->filterMethod = in[27];
if (in[27] != 0) {
PNG_error = 33; // error: only filter method 0 is allowed in the specification
return;
}
info->interlaceMethod = in[28];
if (in[28] > 1) {
PNG_error = 34; // error: only interlace methods 0 and 1 exist in the specification
return;
}
PNG_error = PNG_checkColorValidity(info->colorType, info->bitDepth);
}
int PNG_paethPredictor(int a, int b, int c) // Paeth predicter, used by PNG filter type 4
{
int p, pa, pb, pc;
p = a + b - c;
pa = p > a ? (p - a) : (a - p);
pb = p > b ? (p - b) : (b - p);
pc = p > c ? (p - c) : (c - p);
return (pa <= pb && pa <= pc) ? a : (pb <= pc ? b : c);
}
void PNG_unFilterScanline(uint8_t *recon, const uint8_t *scanline, const uint8_t *precon,
size_t bytewidth, uint32_t filterType, size_t length)
{
size_t i;
switch (filterType) {
case 0:
for (i = 0; i < length; i++)
recon[i] = scanline[i];
break;
case 1:
for (i = 0; i < bytewidth; i++)
recon[i] = scanline[i];
for (i = bytewidth; i < length; i++)
recon[i] = scanline[i] + recon[i - bytewidth];
break;
case 2:
if (precon)
for (i = 0; i < length; i++)
recon[i] = scanline[i] + precon[i];
else
for (i = 0; i < length; i++)
recon[i] = scanline[i];
break;
case 3:
if (precon) {
for (i = 0; i < bytewidth; i++)
recon[i] = scanline[i] + precon[i] / 2;
for (i = bytewidth; i < length; i++)
recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) / 2);
} else {
for (i = 0; i < bytewidth; i++)
recon[i] = scanline[i];
for (i = bytewidth; i < length; i++)
recon[i] = scanline[i] + recon[i - bytewidth] / 2;
}
break;
case 4:
if (precon) {
for (i = 0; i < bytewidth; i++)
recon[i] = (uint8_t) (scanline[i] + PNG_paethPredictor(0, precon[i], 0));
for (i = bytewidth; i < length; i++)
recon[i] = (uint8_t) (scanline[i] + PNG_paethPredictor(recon[i - bytewidth],
precon[i], precon[i - bytewidth]));
} else {
for (i = 0; i < bytewidth; i++)
recon[i] = scanline[i];
for (i = bytewidth; i < length; i++)
recon[i] = (uint8_t) (scanline[i] + PNG_paethPredictor(recon[i - bytewidth], 0, 0));
}
break;
default:
PNG_error = 36; // error: nonexistent filter type given
return;
}
}
void PNG_adam7Pass(uint8_t *out, uint8_t *linen, uint8_t *lineo, const uint8_t *in, uint32_t w,
size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh,
uint32_t bpp)
{// filter and reposition the pixels into the output when the image is Adam7 interlaced. This
// function can only do it after the full image is already decoded. The out buffer must have
// the correct allocated memory size already.
if (passw == 0)
return;
size_t bytewidth = (bpp + 7) / 8, linelength = 1 + ((bpp * passw + 7) / 8);
uint32_t y;
for (y = 0; y < passh; y++) {
size_t i, b;
uint8_t filterType = in[y * linelength], *prevline = (y == 0) ? 0 : lineo;
PNG_unFilterScanline(linen, &in[y * linelength + 1], prevline, bytewidth, filterType,
(w * bpp + 7) / 8);
if (PNG_error)
return;
if (bpp >= 8)
for (i = 0; i < passw; i++)
for (b = 0; b < bytewidth; b++) // b = current byte of this pixel
out[bytewidth * w * (passtop + spacey * y) + bytewidth *
(passleft + spacex * i) + b] = linen[bytewidth * i + b];
else
for (i = 0; i < passw; i++) {
size_t obp, bp;
obp = bpp * w * (passtop + spacey * y) + bpp * (passleft + spacex * i);
bp = i * bpp;
for (b = 0; b < bpp; b++)
PNG_setBitOfReversedStream(&obp, out, PNG_readBitFromReversedStream(&bp, linen));
}
uint8_t *temp = linen;
linen = lineo;
lineo = temp; // swap the two buffer pointers "line old" and "line new"
}
}
int PNG_convert(const PNG_info_t *info, vector8_t *out, const uint8_t *in)
{// converts from any color type to 32-bit. return value = LodePNG error code
size_t i, c;
uint32_t bitDepth, colorType;
bitDepth = info->bitDepth;
colorType = info->colorType;
size_t numpixels = info->width * info->height, bp = 0;
vector8_resize(out, numpixels * 4);
uint8_t *out_data = out->size ? out->data : 0;
if (bitDepth == 8 && colorType == 0) // greyscale
for (i = 0; i < numpixels; i++) {
out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[i];
out_data[4 * i + 3] = (info->key_defined && (in[i] == info->key_r)) ? 0 : 255;
}
else if (bitDepth == 8 && colorType == 2) // RGB color
for (i = 0; i < numpixels; i++) {
for (c = 0; c < 3; c++)
out_data[4 * i + c] = in[3 * i + c];
out_data[4 * i + 3] = (info->key_defined && (in[3 * i + 0] == info->key_r) &&
(in[3 * i + 1] == info->key_g) && (in[3 * i + 2] == info->key_b)) ? 0 : 255;
}
else if (bitDepth == 8 && colorType == 3) // indexed color (palette)
for (i = 0; i < numpixels; i++) {
if (4U * in[i] >= info->palette->size)
return 46;
for (c = 0; c < 4; c++) // get rgb colors from the palette
out_data[4 * i + c] = info->palette->data[4 * in[i] + c];
}
else if (bitDepth == 8 && colorType == 4) // greyscale with alpha
for (i = 0; i < numpixels; i++) {
out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[2 * i + 0];
out_data[4 * i + 3] = in[2 * i + 1];
}
else if (bitDepth == 8 && colorType == 6)
for (i = 0; i < numpixels; i++)
for (c = 0; c < 4; c++)
out_data[4 * i + c] = in[4 * i + c]; // RGB with alpha
else if (bitDepth == 16 && colorType == 0) // greyscale
for (i = 0; i < numpixels; i++) {
out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[2 * i];
out_data[4 * i + 3] = (info->key_defined && (256U * in[i] + in[i + 1] == info->key_r))
? 0 : 255;
}
else if (bitDepth == 16 && colorType == 2) // RGB color
for (i = 0; i < numpixels; i++) {
for (c = 0; c < 3; c++)
out_data[4 * i + c] = in[6 * i + 2 * c];
out_data[4 * i + 3] = (info->key_defined &&
(256U * in[6 * i + 0] + in[6 * i + 1] == info->key_r) &&
(256U * in[6 * i + 2] + in[6 * i + 3] == info->key_g) &&
(256U * in[6 * i + 4] + in[6 * i + 5] == info->key_b)) ? 0 : 255;
}
else if (bitDepth == 16 && colorType == 4) // greyscale with alpha
for (i = 0; i < numpixels; i++) {
out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = in[4 * i]; // msb
out_data[4 * i + 3] = in[4 * i + 2];
}
else if (bitDepth == 16 && colorType == 6)
for (i = 0; i < numpixels; i++)
for (c = 0; c < 4; c++)
out_data[4 * i + c] = in[8 * i + 2 * c]; // RGB with alpha
else if (bitDepth < 8 && colorType == 0) // greyscale
for (i = 0; i < numpixels; i++) {
uint32_t value = (PNG_readBitsFromReversedStream(&bp, in, bitDepth) * 255) /
((1 << bitDepth) - 1); // scale value from 0 to 255
out_data[4 * i + 0] = out_data[4 * i + 1] = out_data[4 * i + 2] = (uint8_t) value;
out_data[4 * i + 3] = (info->key_defined && value &&
(((1U << bitDepth) - 1U) == info->key_r) && ((1U << bitDepth) - 1U)) ? 0 : 255;
}
else if (bitDepth < 8 && colorType == 3) // palette
for (i = 0; i < numpixels; i++) {
uint32_t value = PNG_readBitsFromReversedStream(&bp, in, bitDepth);
if (4 * value >= info->palette->size)
return 47;
for (c = 0; c < 4; c++) // get rgb colors from the palette
out_data[4 * i + c] = info->palette->data[4 * value + c];
}
return 0;
}
PNG_info_t *PNG_info_new()
{
PNG_info_t *info = png_alloc_malloc(sizeof (PNG_info_t));
uint32_t i;
for (i = 0; i < sizeof (PNG_info_t); i++)
((uint8_t *) info)[i] = 0;
info->palette = vector8_new(0, 0);
info->image = vector8_new(0, 0);
return info;
}
PNG_info_t *PNG_decode(const uint8_t *in, uint32_t size)
{
PNG_info_t *info;
PNG_error = 0;
if (size == 0 || in == 0) {
PNG_error = 48; // the given data is empty
return NULL;
}
info = PNG_info_new();
PNG_readPngHeader(info, in, size);
if (PNG_error)
return NULL;
size_t pos = 33; // first byte of the first chunk after the header
vector8_t *idat = NULL; // the data from idat chunks
bool IEND = false, known_type = true;
info->key_defined = false;
// loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. IDAT data is
// put at the start of the in buffer
while (!IEND) {
size_t i, j;
if (pos + 8 >= size) {
PNG_error = 30; // error: size of the in buffer too small to contain next chunk
return NULL;
}
size_t chunkLength = PNG_read32bitInt(&in[pos]);
pos += 4;
if (chunkLength > 0x7fffffff) {
PNG_error = 63;
return NULL;
}
if (pos + chunkLength >= size) {
PNG_error = 35; // error: size of the in buffer too small to contain next chunk
return NULL;
}
uint32_t chunkType = *(uint32_t *) &in[pos];
if (chunkType == CHUNK_IDAT) { // IDAT: compressed image data chunk
size_t offset = 0;
if (idat) {
offset = idat->size;
vector8_resize(idat, offset + chunkLength);
} else
idat = vector8_new(chunkLength, 0);
for (i = 0; i < chunkLength; i++)
idat->data[offset + i] = in[pos + 4 + i];
pos += (4 + chunkLength);
} else if (chunkType == CHUNK_IEND) { // IEND
pos += 4;
IEND = true;
} else if (chunkType == CHUNK_PLTE) { // PLTE: palette chunk
pos += 4; // go after the 4 letters
vector8_resize(info->palette, 4 * (chunkLength / 3));
if (info->palette->size > (4 * 256)) {
PNG_error = 38; // error: palette too big
return NULL;
}
for (i = 0; i < info->palette->size; i += 4) {
for (j = 0; j < 3; j++)
info->palette->data[i + j] = in[pos++]; // RGB
info->palette->data[i + 3] = 255; // alpha
}
} else if (chunkType == CHUNK_tRNS) { // tRNS: palette transparency chunk
pos += 4; // go after the 4 letters
if (info->colorType == 3) {
if (4 * chunkLength > info->palette->size) {
PNG_error = 39; // error: more alpha values given than there are palette entries
return NULL;
}
for (i = 0; i < chunkLength; i++)
info->palette->data[4 * i + 3] = in[pos++];
} else if (info->colorType == 0) {
if (chunkLength != 2) {
PNG_error = 40; // error: this chunk must be 2 bytes for greyscale image
return NULL;
}
info->key_defined = true;
info->key_r = info->key_g = info->key_b = 256 * in[pos] + in[pos + 1];
pos += 2;
} else if (info->colorType == 2) {
if (chunkLength != 6) {
PNG_error = 41; // error: this chunk must be 6 bytes for RGB image
return NULL;
}
info->key_defined = true;
info->key_r = 256 * in[pos] + in[pos + 1];
pos += 2;
info->key_g = 256 * in[pos] + in[pos + 1];
pos += 2;
info->key_b = 256 * in[pos] + in[pos + 1];
pos += 2;
} else {
PNG_error = 42; // error: tRNS chunk not allowed for other color models
return NULL;
}
} else { // it's not an implemented chunk type, so ignore it: skip over the data
if (!(in[pos + 0] & 32)) {
// error: unknown critical chunk (5th bit of first byte of chunk type is 0)
PNG_error = 69;
return NULL;
}
pos += (chunkLength + 4); // skip 4 letters and uninterpreted data of unimplemented chunk
known_type = false;
}
pos += 4; // step over CRC (which is ignored)
}
uint32_t bpp = PNG_getBpp(info);
vector8_t *scanlines; // now the out buffer will be filled
scanlines = vector8_new(((info->width * (info->height * bpp + 7)) / 8) + info->height, 0);
PNG_error = Zlib_decompress(scanlines, idat);
if (PNG_error)
return NULL; // stop if the zlib decompressor returned an error
size_t bytewidth = (bpp + 7) / 8, outlength = (info->height * info->width * bpp + 7) / 8;
vector8_resize(info->image, outlength); // time to fill the out buffer
uint8_t *out_data = outlength ? info->image->data : 0;
if (info->interlaceMethod == 0) { // no interlace, just filter
size_t y, obp, bp;
size_t linestart, linelength;
linestart = 0;
// length in bytes of a scanline, excluding the filtertype byte
linelength = (info->width * bpp + 7) / 8;
if (bpp >= 8) // byte per byte
for (y = 0; y < info->height; y++) {
uint32_t filterType = scanlines->data[linestart];
const uint8_t *prevline;
prevline = (y == 0) ? 0 : &out_data[(y - 1) * info->width * bytewidth];
PNG_unFilterScanline(&out_data[linestart - y], &scanlines->data[linestart + 1],
prevline, bytewidth, filterType, linelength);
if (PNG_error)
return NULL;
linestart += (1 + linelength); // go to start of next scanline
} else { // less than 8 bits per pixel, so fill it up bit per bit
vector8_t *templine; // only used if bpp < 8
templine = vector8_new((info->width * bpp + 7) >> 3, 0);
for (y = 0, obp = 0; y < info->height; y++) {
uint32_t filterType = scanlines->data[linestart];
const uint8_t *prevline;
prevline = (y == 0) ? 0 : &out_data[(y - 1) * info->width * bytewidth];
PNG_unFilterScanline(templine->data, &scanlines->data[linestart + 1], prevline,
bytewidth, filterType, linelength);
if (PNG_error)
return NULL;
for (bp = 0; bp < info->width * bpp;)
PNG_setBitOfReversedStream(&obp, out_data, PNG_readBitFromReversedStream(&bp,
templine->data));
linestart += (1 + linelength); // go to start of next scanline
}
}
} else { // interlaceMethod is 1 (Adam7)
int i;
size_t passw[7] = {
(info->width + 7) / 8, (info->width + 3) / 8, (info->width + 3) / 4,
(info->width + 1) / 4, (info->width + 1) / 2, (info->width + 0) / 2,
(info->width + 0) / 1
};
size_t passh[7] = {
(info->height + 7) / 8, (info->height + 7) / 8, (info->height + 3) / 8,
(info->height + 3) / 4, (info->height + 1) / 4, (info->height + 1) / 2,
(info->height + 0) / 2
};
size_t passstart[7] = { 0 };
size_t pattern[28] = { 0, 4, 0, 2, 0, 1, 0, 0, 0, 4, 0, 2, 0, 1, 8, 8, 4, 4, 2, 2, 1, 8, 8,
8, 4, 4, 2, 2 }; // values for the adam7 passes
for (i = 0; i < 6; i++)
passstart[i + 1] = passstart[i] + passh[i] * ((passw[i] ? 1 : 0) + (passw[i] * bpp + 7) / 8);
vector8_t *scanlineo, *scanlinen; // "old" and "new" scanline
scanlineo = vector8_new((info->width * bpp + 7) / 8, 0);
scanlinen = vector8_new((info->width * bpp + 7) / 8, 0);
for (i = 0; i < 7; i++)
PNG_adam7Pass(out_data, scanlinen->data, scanlineo->data, &scanlines->data[passstart[i]],
info->width, pattern[i], pattern[i + 7], pattern[i + 14], pattern[i + 21],
passw[i], passh[i], bpp);
}
if (info->colorType != 6 || info->bitDepth != 8) { // conversion needed
vector8_t *copy = vector8_copy(info->image); // xxx: is this copy necessary?
PNG_error = PNG_convert(info, info->image, copy->data);
}
return info;
}
/*************************************************************************************************/
#ifdef TEST
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char **argv)
{
char *fname = (argc > 1) ? argv[1] : "test.png";
PNG_info_t *info;
struct stat statbuf;
uint32_t insize, outsize;
FILE *infp, *outfp;
uint8_t *inbuf;
uint32_t n;
if (stat(fname, &statbuf) != 0) {
perror("stat");
return 1;
} else if (!statbuf.st_size) {
printf("file empty\n");
return 1;
}
insize = (uint32_t) statbuf.st_size;
inbuf = malloc(insize);
infp = fopen(fname, "rb");
if (!infp) {
perror("fopen");
return 1;
} else if (fread(inbuf, 1, insize, infp) != insize) {
perror("fread");
return 1;
}
fclose(infp);
printf("input file: %s (size: %d)\n", fname, insize);
info = PNG_decode(inbuf, insize);
free(inbuf);
printf("PNG_error: %d\n", PNG_error);
if (PNG_error != 0)
return 1;
printf("width: %d, height: %d\nfirst 16 bytes: ", info->width, info->height);
for (n = 0; n < 16; n++)
printf("%02x ", info->image->data[n]);
printf("\n");
outsize = info->width * info->height * 4;
printf("image size: %d\n", outsize);
if (outsize != info->image->size) {
printf("error: image size doesn't match dimensions\n");
return 1;
}
outfp = fopen("out.bin", "wb");
if (!outfp) {
perror("fopen");
return 1;
} else if (fwrite(info->image->data, 1, outsize, outfp) != outsize) {
perror("fwrite");
return 1;
}
fclose(outfp);
#ifdef ALLOC_DEBUG
png_alloc_node_t *node;
for (node = png_alloc_head, n = 1; node; node = node->next, n++)
printf("node %d (%p) addr = %p, size = %ld\n", n, node, node->addr, node->size);
#endif
png_alloc_free_all(); // also frees info and image data from PNG_decode
return 0;
}
#endif
branches/rewrite/i386/boot2/graphic_utils.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/* Graphic utility functions and data types
* Prashant Vaibhav (C) 12/12/2008
* Chameleon
*/
// Everything here is 32 bits per pixel non-premultiplied ARGB format
//
#ifndef GRAPHIC_UTILS_H
#define GRAPHIC_UTILS_H
#include "boot.h"
typedef union {
struct {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} ch;
uint8_t channel[4];
uint32_t value;
} pixel_t;
typedef struct {
uint16_theight;
uint16_twidth;
pixel_t*pixels;
} pixmap_t;
typedef struct {
uint32_t x;
uint32_t y;
} position_t;
// Blends the given pixmap into the given background at the given position
// Uses the alpha channels to blend, and preserves the final alpha (so the
// resultant pixmap can be blended again with another background).
// ported from www.stereopsis.com/doubleblend.html
void blend( const pixmap_t *blendThis, // Source image
pixmap_t *blendInto, // Dest image
const position_t position); // Where to place the source image
// Returns the topleft co-ordinate where if you put the 'toCenter' pixmap,
// it is centered in the background.
position_t centeredIn( const pixmap_t *background, const pixmap_t *toCenter );
// Returns the topleft co-ordinate where if you put the given pixmap, its
// center will coincide with the th given center.
position_t centeredAt( const pixmap_t *pixmap, const position_t center );
// Utility function returns a position_t struct given the x and y coords as uint16
position_t pos(const uint16_t x, const uint16_t y);
// Flips the R and B components of all pixels in the given pixmap
void flipRB(pixmap_t *p);
// Utility function to get pixel at (x,y) in a pixmap
#define pixel(p,x,y) ((p)->pixels[(x) + (y) * (p)->width])
#endif//GRAPHIC_UTILS_H
branches/rewrite/i386/boot2/picopng.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#ifndef _PICOPNG_H
#define _PICOPNG_H
#include <stdint.h>
typedef struct {
uint32_t *data;
size_t size;
size_t allocsize;
} vector32_t;
typedef struct {
uint8_t *data;
size_t size;
size_t allocsize;
} vector8_t;
typedef struct {
uint32_t width, height;
uint32_t colorType, bitDepth;
uint32_t compressionMethod, filterMethod, interlaceMethod;
uint32_t key_r, key_g, key_b;
bool key_defined; // is a transparent color key given?
vector8_t *palette;
vector8_t *image;
} PNG_info_t;
PNG_info_t *PNG_decode(const uint8_t *in, uint32_t size);
void png_alloc_free_all();
extern int PNG_error;
#endif
branches/rewrite/i386/boot2/graphics.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
* graphics.h
*
*
* Created by fassl on 22.12.08.
* Copyright 2008 __MyCompanyName__. All rights reserved.
*
*/
#include "boot.h"
#include "bootstruct.h"
#include "graphic_utils.h"
#ifndef __BOOT_GRAPHICS_H
#define __BOOT_GRAPHICS_H
#define DEFAULT_SCREEN_WIDTH 1024
#define DEFAULT_SCREEN_HEIGHT 768
int loadPngImage(const char *filename, uint16_t *width, uint16_t *height, uint8_t **imageData);
unsigned long lookUpCLUTIndex( unsigned char index, unsigned char depth );
void drawColorRectangle( unsigned short x, unsigned short y, unsigned short width, unsigned short height, unsigned char colorIndex );
void drawDataRectangle( unsigned short x, unsigned short y, unsigned short width, unsigned short height, unsigned char * data );
int convertImage( unsigned short width, unsigned short height, const unsigned char *imageData, unsigned char **newImageData );
int initGraphicsMode ();
void drawCheckerBoard();
void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t *data);
void drawCheckerBoard();
void blendImage(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t *data);
int loadEmbeddedPngImage(uint8_t *pngData, int pngSize, uint16_t *width, uint16_t *height, uint8_t **imageData);
char *getVBEInfoString();
char *getVBEModeInfoString();
void getGraphicModeParams(unsigned long params[]);
#endif /* !__BOOT_GRAPHICS_H */
branches/rewrite/i386/boot2/drivers.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
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
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
/*
* Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 2.0 (the 'License'). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* drivers.c - Driver Loading Functions.
*
* Copyright (c) 2000 Apple Computer, Inc.
*
* DRI: Josh de Cesare
*/
#include <mach-o/fat.h>
#include <libkern/OSByteOrder.h>
#include <mach/machine.h>
#include "sl.h"
#include "boot.h"
#include "bootstruct.h"
#include "xml.h"
#include "ramdisk.h"
#include "modules.h"
//extern char gMacOSVersion[8];
struct Module {
struct Module *nextModule;
long willLoad;
TagPtr dict;
char *plistAddr;
long plistLength;
char *executablePath;
char *bundlePath;
long bundlePathLength;
};
typedef struct Module Module, *ModulePtr;
struct DriverInfo {
char *plistAddr;
long plistLength;
void *executableAddr;
long executableLength;
void *bundlePathAddr;
long bundlePathLength;
};
typedef struct DriverInfo DriverInfo, *DriverInfoPtr;
#define kDriverPackageSignature1 'MKXT'
#define kDriverPackageSignature2 'MOSX'
struct DriversPackage {
unsigned long signature1;
unsigned long signature2;
unsigned long length;
unsigned long adler32;
unsigned long version;
unsigned long numDrivers;
unsigned long reserved1;
unsigned long reserved2;
};
typedef struct DriversPackage DriversPackage;
enum {
kCFBundleType2,
kCFBundleType3
};
long (*LoadExtraDrivers_p)(FileLoadDrivers_t FileLoadDrivers_p);
/*static*/ unsigned long Adler32( unsigned char * buffer, long length );
static long FileLoadDrivers(char *dirSpec, long plugin);
static long NetLoadDrivers(char *dirSpec);
static long LoadDriverMKext(char *fileSpec);
static long LoadDriverPList(char *dirSpec, char *name, long bundleType);
static long LoadMatchedModules(void);
static long MatchPersonalities(void);
static long MatchLibraries(void);
#ifdef NOTDEF
static ModulePtr FindModule(char *name);
static void ThinFatFile(void **loadAddrP, unsigned long *lengthP);
#endif
static long ParseXML(char *buffer, ModulePtr *module, TagPtr *personalities);
static long InitDriverSupport(void);
static ModulePtr gModuleHead, gModuleTail;
static TagPtr gPersonalityHead, gPersonalityTail;
static char * gExtensionsSpec;
static char * gDriverSpec;
static char * gFileSpec;
static char * gTempSpec;
static char * gFileName;
/*static*/ unsigned long
Adler32( unsigned char * buffer, long length )
{
long cnt;
unsigned long result, lowHalf, highHalf;
lowHalf = 1;
highHalf = 0;
for ( cnt = 0; cnt < length; cnt++ )
{
if ((cnt % 5000) == 0)
{
lowHalf %= 65521L;
highHalf %= 65521L;
}
lowHalf += buffer[cnt];
highHalf += lowHalf;
}
lowHalf %= 65521L;
highHalf %= 65521L;
result = (highHalf << 16) | lowHalf;
return result;
}
//==========================================================================
// InitDriverSupport
static long
InitDriverSupport( void )
{
gExtensionsSpec = malloc( 4096 );
gDriverSpec = malloc( 4096 );
gFileSpec = malloc( 4096 );
gTempSpec = malloc( 4096 );
gFileName = malloc( 4096 );
if ( !gExtensionsSpec || !gDriverSpec || !gFileSpec || !gTempSpec || !gFileName )
stop("InitDriverSupport error");
return 0;
}
//==========================================================================
// LoadDrivers
long LoadDrivers( char * dirSpec )
{
char dirSpecExtra[1024];
if ( InitDriverSupport() != 0 )
return 0;
// Load extra drivers if a hook has been installed.
if (LoadExtraDrivers_p != NULL)
{
(*LoadExtraDrivers_p)(&FileLoadDrivers);
}
if ( gBootFileType == kNetworkDeviceType )
{
if (NetLoadDrivers(dirSpec) != 0) {
error("Could not load drivers from the network\n");
return -1;
}
}
else if ( gBootFileType == kBlockDeviceType )
{
// First try to load Extra extensions from the ramdisk if isn't aliased as bt(0,0).
if (gRAMDiskVolume && !gRAMDiskBTAliased)
{
strcpy(dirSpecExtra, "rd(0,0)/Extra/");
FileLoadDrivers(dirSpecExtra, 0);
}
// Next try to load Extra extensions from the selected root partition.
strcpy(dirSpecExtra, "/Extra/");
if (FileLoadDrivers(dirSpecExtra, 0) != 0)
{
// If failed, then try to load Extra extensions from the boot partition
// in case we have a separate booter partition or a bt(0,0) aliased ramdisk.
if ( !(gBIOSBootVolume->biosdev == gBootVolume->biosdev && gBIOSBootVolume->part_no == gBootVolume->part_no)
|| (gRAMDiskVolume && gRAMDiskBTAliased) )
{
// Next try a specfic OS version folder ie 10.5
sprintf(dirSpecExtra, "bt(0,0)/Extra/%s/", &gMacOSVersion);
if (FileLoadDrivers(dirSpecExtra, 0) != 0)
{
// Next we'll try the base
strcpy(dirSpecExtra, "bt(0,0)/Extra/");
FileLoadDrivers(dirSpecExtra, 0);
}
}
}
// Also try to load Extensions from boot helper partitions.
if (gBootVolume->flags & kBVFlagBooter)
{
strcpy(dirSpecExtra, "/com.apple.boot.P/System/Library/");
if (FileLoadDrivers(dirSpecExtra, 0) != 0)
{
strcpy(dirSpecExtra, "/com.apple.boot.R/System/Library/");
if (FileLoadDrivers(dirSpecExtra, 0) != 0)
{
strcpy(dirSpecExtra, "/com.apple.boot.S/System/Library/");
FileLoadDrivers(dirSpecExtra, 0);
}
}
}
if (gMKextName[0] != '\0')
{
verbose("LoadDrivers: Loading from [%s]\n", gMKextName);
if ( LoadDriverMKext(gMKextName) != 0 )
{
error("Could not load %s\n", gMKextName);
return -1;
}
}
else
{
strcpy(gExtensionsSpec, dirSpec);
strcat(gExtensionsSpec, "System/Library/");
FileLoadDrivers(gExtensionsSpec, 0);
}
}
else
{
return 0;
}
MatchPersonalities();
MatchLibraries();
LoadMatchedModules();
return 0;
}
//==========================================================================
// FileLoadMKext
static long
FileLoadMKext( const char * dirSpec, const char * extDirSpec )
{
longret, flags, time, time2;
charaltDirSpec[512];
sprintf (altDirSpec, "%s%s", dirSpec, extDirSpec);
ret = GetFileInfo(altDirSpec, "Extensions.mkext", &flags, &time);
if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeFlat))
{
ret = GetFileInfo(dirSpec, "Extensions", &flags, &time2);
if ((ret != 0)
|| ((flags & kFileTypeMask) != kFileTypeDirectory)
|| (((gBootMode & kBootModeSafe) == 0) && (time == (time2 + 1))))
{
sprintf(gDriverSpec, "%sExtensions.mkext", altDirSpec);
if (LoadDriverMKext(gDriverSpec) == 0)
return 0;
}
}
return -1;
}
//==========================================================================
// FileLoadDrivers
static long
FileLoadDrivers( char * dirSpec, long plugin )
{
long ret, length, flags, time, bundleType;
long long index;
long result = -1;
const char * name;
if ( !plugin )
{
// First try 10.6's path for loading Extensions.mkext.
if (FileLoadMKext(dirSpec, "Caches/com.apple.kext.caches/Startup/") == 0)
return 0;
// Next try the legacy path.
else if (FileLoadMKext(dirSpec, "") == 0)
return 0;
strcat(dirSpec, "Extensions");
}
index = 0;
while (1) {
ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);
if (ret == -1) break;
// Make sure this is a directory.
if ((flags & kFileTypeMask) != kFileTypeDirectory) continue;
// Make sure this is a kext.
length = strlen(name);
if (strcmp(name + length - 5, ".kext")) continue;
// Save the file name.
strcpy(gFileName, name);
// Determine the bundle type.
sprintf(gTempSpec, "%s/%s", dirSpec, gFileName);
ret = GetFileInfo(gTempSpec, "Contents", &flags, &time);
if (ret == 0) bundleType = kCFBundleType2;
else bundleType = kCFBundleType3;
if (!plugin)
sprintf(gDriverSpec, "%s/%s/%sPlugIns", dirSpec, gFileName,
(bundleType == kCFBundleType2) ? "Contents/" : "");
ret = LoadDriverPList(dirSpec, gFileName, bundleType);
if (result != 0)
result = ret;
if (!plugin)
FileLoadDrivers(gDriverSpec, 1);
}
return result;
}
//==========================================================================
//
static long
NetLoadDrivers( char * dirSpec )
{
long tries;
#if NODEF
long cnt;
// Get the name of the kernel
cnt = strlen(gBootFile);
while (cnt--) {
if ((gBootFile[cnt] == '\\') || (gBootFile[cnt] == ',')) {
cnt++;
break;
}
}
#endif
// INTEL modification
sprintf(gDriverSpec, "%s%s.mkext", dirSpec, bootInfo->bootFile);
verbose("NetLoadDrivers: Loading from [%s]\n", gDriverSpec);
tries = 3;
while (tries--)
{
if (LoadDriverMKext(gDriverSpec) == 0) break;
}
if (tries == -1) return -1;
return 0;
}
//==========================================================================
// loadDriverMKext
static long
LoadDriverMKext( char * fileSpec )
{
unsigned long driversAddr, driversLength;
long length;
char segName[32];
DriversPackage * package;
#define GetPackageElement(e) OSSwapBigToHostInt32(package->e)
// Load the MKext.
length = LoadThinFatFile(fileSpec, (void **)&package);
if (length < sizeof (DriversPackage)) return -1;
// call hook to notify modules that the mkext has been loaded
execute_hook("LoadDriverMKext", (void*)fileSpec, (void*)package, (void*) &length, NULL);
// Verify the MKext.
if (( GetPackageElement(signature1) != kDriverPackageSignature1) ||
( GetPackageElement(signature2) != kDriverPackageSignature2) ||
( GetPackageElement(length) > kLoadSize ) ||
( GetPackageElement(adler32) !=
Adler32((unsigned char *)&package->version, GetPackageElement(length) - 0x10) ) )
{
return -1;
}
// Make space for the MKext.
driversLength = GetPackageElement(length);
driversAddr = AllocateKernelMemory(driversLength);
// Copy the MKext.
memcpy((void *)driversAddr, (void *)package, driversLength);
// Add the MKext to the memory map.
sprintf(segName, "DriversPackage-%lx", driversAddr);
AllocateMemoryRange(segName, driversAddr, driversLength,
kBootDriverTypeMKEXT);
return 0;
}
//==========================================================================
// LoadDriverPList
static long
LoadDriverPList( char * dirSpec, char * name, long bundleType )
{
long length, executablePathLength, bundlePathLength;
ModulePtr module;
TagPtr personalities;
char * buffer = 0;
char * tmpExecutablePath = 0;
char * tmpBundlePath = 0;
long ret = -1;
do {
// Save the driver path.
sprintf(gFileSpec, "%s/%s/%s", dirSpec, name,
(bundleType == kCFBundleType2) ? "Contents/MacOS/" : "");
executablePathLength = strlen(gFileSpec) + 1;
tmpExecutablePath = malloc(executablePathLength);
if (tmpExecutablePath == 0) break;
strcpy(tmpExecutablePath, gFileSpec);
sprintf(gFileSpec, "%s/%s", dirSpec, name);
bundlePathLength = strlen(gFileSpec) + 1;
tmpBundlePath = malloc(bundlePathLength);
if (tmpBundlePath == 0) break;
strcpy(tmpBundlePath, gFileSpec);
// Construct the file spec to the plist, then load it.
sprintf(gFileSpec, "%s/%s/%sInfo.plist", dirSpec, name,
(bundleType == kCFBundleType2) ? "Contents/" : "");
length = LoadFile(gFileSpec);
if (length == -1) break;
length = length + 1;
buffer = malloc(length);
if (buffer == 0) break;
strlcpy(buffer, (char *)kLoadAddr, length);
// Parse the plist.
ret = ParseXML(buffer, &module, &personalities);
if (ret != 0) { break; }
// Allocate memory for the driver path and the plist.
module->executablePath = tmpExecutablePath;
module->bundlePath = tmpBundlePath;
module->bundlePathLength = bundlePathLength;
module->plistAddr = malloc(length);
if ((module->executablePath == 0) || (module->bundlePath == 0) || (module->plistAddr == 0))
break;
// Save the driver path in the module.
//strcpy(module->driverPath, tmpDriverPath);
tmpExecutablePath = 0;
tmpBundlePath = 0;
// Add the plist to the module.
strlcpy(module->plistAddr, (char *)kLoadAddr, length);
module->plistLength = length;
// Add the module to the end of the module list.
if (gModuleHead == 0)
gModuleHead = module;
else
gModuleTail->nextModule = module;
gModuleTail = module;
// Add the persionalities to the personality list.
if (personalities) personalities = personalities->tag;
while (personalities != 0)
{
if (gPersonalityHead == 0)
gPersonalityHead = personalities->tag;
else
gPersonalityTail->tagNext = personalities->tag;
gPersonalityTail = personalities->tag;
personalities = personalities->tagNext;
}
ret = 0;
}
while (0);
if ( buffer ) free( buffer );
if ( tmpExecutablePath ) free( tmpExecutablePath );
if ( tmpBundlePath ) free( tmpBundlePath );
return ret;
}
//==========================================================================
// LoadMatchedModules
static long
LoadMatchedModules( void )
{
TagPtr prop;
ModulePtr module;
char *fileName, segName[32];
DriverInfoPtr driver;
long length, driverAddr, driverLength;
void *executableAddr = 0;
module = gModuleHead;
while (module != 0)
{
if (module->willLoad)
{
prop = XMLGetProperty(module->dict, kPropCFBundleExecutable);
if (prop != 0)
{
fileName = prop->string;
sprintf(gFileSpec, "%s%s", module->executablePath, fileName);
length = LoadThinFatFile(gFileSpec, &executableAddr);
if (length == 0)
{
length = LoadFile(gFileSpec);
executableAddr = (void *)kLoadAddr;
}
//printf("%s length = %d addr = 0x%x\n", gFileSpec, length, driverModuleAddr); getchar();
}
else
length = 0;
if (length != -1)
{
//driverModuleAddr = (void *)kLoadAddr;
//if (length != 0)
//{
//ThinFatFile(&driverModuleAddr, &length);
//}
// Make make in the image area.
driverLength = sizeof(DriverInfo) + module->plistLength + length + module->bundlePathLength;
driverAddr = AllocateKernelMemory(driverLength);
// Set up the DriverInfo.
driver = (DriverInfoPtr)driverAddr;
driver->plistAddr = (char *)(driverAddr + sizeof(DriverInfo));
driver->plistLength = module->plistLength;
if (length != 0)
{
driver->executableAddr = (void *)(driverAddr + sizeof(DriverInfo) +
module->plistLength);
driver->executableLength = length;
}
else
{
driver->executableAddr = 0;
driver->executableLength = 0;
}
driver->bundlePathAddr = (void *)(driverAddr + sizeof(DriverInfo) +
module->plistLength + driver->executableLength);
driver->bundlePathLength = module->bundlePathLength;
// Save the plist, module and bundle.
strcpy(driver->plistAddr, module->plistAddr);
if (length != 0)
{
memcpy(driver->executableAddr, executableAddr, length);
}
strcpy(driver->bundlePathAddr, module->bundlePath);
// Add an entry to the memory map.
sprintf(segName, "Driver-%lx", (unsigned long)driver);
AllocateMemoryRange(segName, driverAddr, driverLength,
kBootDriverTypeKEXT);
}
}
module = module->nextModule;
}
return 0;
}
//==========================================================================
// MatchPersonalities
static long
MatchPersonalities( void )
{
/* IONameMatch support not implemented */
return 0;
}
//==========================================================================
// MatchLibraries
static long
MatchLibraries( void )
{
TagPtr prop, prop2;
ModulePtr module, module2;
long done;
do {
done = 1;
module = gModuleHead;
while (module != 0)
{
if (module->willLoad == 1)
{
prop = XMLGetProperty(module->dict, kPropOSBundleLibraries);
if (prop != 0)
{
prop = prop->tag;
while (prop != 0)
{
module2 = gModuleHead;
while (module2 != 0)
{
prop2 = XMLGetProperty(module2->dict, kPropCFBundleIdentifier);
if ((prop2 != 0) && (!strcmp(prop->string, prop2->string)))
{
if (module2->willLoad == 0) module2->willLoad = 1;
break;
}
module2 = module2->nextModule;
}
prop = prop->tagNext;
}
}
module->willLoad = 2;
done = 0;
}
module = module->nextModule;
}
}
while (!done);
return 0;
}
//==========================================================================
// FindModule
#if NOTDEF
static ModulePtr
FindModule( char * name )
{
ModulePtr module;
TagPtr prop;
module = gModuleHead;
while (module != 0)
{
prop = GetProperty(module->dict, kPropCFBundleIdentifier);
if ((prop != 0) && !strcmp(name, prop->string)) break;
module = module->nextModule;
}
return module;
}
#endif /* NOTDEF */
//==========================================================================
// ParseXML
static long
ParseXML( char * buffer, ModulePtr * module, TagPtr * personalities )
{
long length, pos;
TagPtr moduleDict, required;
ModulePtr tmpModule;
pos = 0;
while (1)
{
length = XMLParseNextTag(buffer + pos, &moduleDict);
if (length == -1) break;
pos += length;
if (moduleDict == 0) continue;
if (moduleDict->type == kTagTypeDict) break;
XMLFreeTag(moduleDict);
}
if (length == -1) return -1;
required = XMLGetProperty(moduleDict, kPropOSBundleRequired);
if ( (required == 0) ||
(required->type != kTagTypeString) ||
!strcmp(required->string, "Safe Boot"))
{
XMLFreeTag(moduleDict);
return -2;
}
tmpModule = malloc(sizeof(Module));
if (tmpModule == 0)
{
XMLFreeTag(moduleDict);
return -1;
}
tmpModule->dict = moduleDict;
// For now, load any module that has OSBundleRequired != "Safe Boot".
tmpModule->willLoad = 1;
*module = tmpModule;
// Get the personalities.
*personalities = XMLGetProperty(moduleDict, kPropIOKitPersonalities);
return 0;
}
#if NOTDEF
static char gPlatformName[64];
#endif
long
DecodeKernel(void *binary, entry_t *rentry, char **raddr, int *rsize)
{
long ret;
compressed_kernel_header * kernel_header = (compressed_kernel_header *) binary;
u_int32_t uncompressed_size, size;
void *buffer;
unsigned long len;
#if 0
printf("kernel header:\n");
printf("signature: 0x%x\n", kernel_header->signature);
printf("compress_type: 0x%x\n", kernel_header->compress_type);
printf("adler32: 0x%x\n", kernel_header->adler32);
printf("uncompressed_size: 0x%x\n", kernel_header->uncompressed_size);
printf("compressed_size: 0x%x\n", kernel_header->compressed_size);
getchar();
#endif
if (kernel_header->signature == OSSwapBigToHostConstInt32('comp'))
{
if (kernel_header->compress_type != OSSwapBigToHostConstInt32('lzss'))
{
error("kernel compression is bad\n");
return -1;
}
#if NOTDEF
if (kernel_header->platform_name[0] && strcmp(gPlatformName, kernel_header->platform_name))
return -1;
if (kernel_header->root_path[0] && strcmp(gBootFile, kernel_header->root_path))
return -1;
#endif
uncompressed_size = OSSwapBigToHostInt32(kernel_header->uncompressed_size);
binary = buffer = malloc(uncompressed_size);
size = decompress_lzss((u_int8_t *) binary, &kernel_header->data[0],
OSSwapBigToHostInt32(kernel_header->compressed_size));
if (uncompressed_size != size) {
error("size mismatch from lzss: %x\n", size);
return -1;
}
if (OSSwapBigToHostInt32(kernel_header->adler32) !=
Adler32(binary, uncompressed_size))
{
printf("adler mismatch\n");
return -1;
}
}
// Notify modules that the kernel has been decompressed, is about to be decoded
execute_hook("DecodeKernel", (void*)binary, NULL, NULL, NULL);
ret = ThinFatFile(&binary, &len);
if (ret == 0 && len == 0 && archCpuType==CPU_TYPE_X86_64)
{
archCpuType=CPU_TYPE_I386;
ret = ThinFatFile(&binary, &len);
}
ret = DecodeMachO(binary, rentry, raddr, rsize);
if (ret<0 && archCpuType==CPU_TYPE_X86_64)
{
archCpuType=CPU_TYPE_I386;
ret = DecodeMachO(binary, rentry, raddr, rsize);
}
return ret;
}
branches/rewrite/i386/boot2/prompt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
* Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 2.0 (the "License"). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Copyright 1993 NeXT, Inc.
* All rights reserved.
*/
#include <vers.h>
char bootBanner[] = "\nDarwin/x86 boot v" I386BOOT_VERSION " - Chameleon v" I386BOOT_CHAMELEONVERSION " r" I386BOOT_CHAMELEONREVISION "\n"
"Build date: " I386BOOT_BUILDDATE "\n"
"%dMB memory\n";
char bootPrompt[] =
"Press Enter to start up Darwin/x86 with no options, or you can:\n"
" Type -v and press Enter to start up with diagnostic messages\n"
" Type ? and press Enter to learn about advanced startup options\n\n"
"boot: ";
char bootRescanPrompt[] =
"Press Enter to start up Darwin/x86 with no options, or you can:\n"
" Press F5 after you swapped the media. The drive will be rescanned.\n"
" Type -v and press Enter to start up with diagnostic messages\n"
" Type ? and press Enter to learn about advanced startup options\n\n"
"boot: ";
branches/rewrite/i386/boot2/WKdmDecompress.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#include <sys/cdefs.h>
#include "WKdm.h"
/* Part of __HIB section */
/***************************************************************************
* THE UNPACKING ROUTINES should GO HERE
*/
const char hashLookupTable [] = HASH_LOOKUP_TABLE_CONTENTS;
#if 0
#define GET_NEXT_TAG tags[tagsIndex++]
#define GET_NEXT_FULL_PATTERN fullPatterns[fullPatternsIndex++]
#define GET_NEXT_LOW_BITS lowBits[lowBitsIndex++]
#define GET_NEXT_DICTIONARY_INDEX dictionaryIndices[dictionaryIndicesIndex++]
#endif
/* WK_unpack_2bits takes any number of words containing 16 two-bit values
* and unpacks them into four times as many words containg those
* two bit values as bytes (with the low two bits of each byte holding
* the actual value.
*/
static WK_word*
WK_unpack_2bits(WK_word *input_buf,
WK_word *input_end,
WK_word *output_buf) {
register WK_word *input_next = input_buf;
register WK_word *output_next = output_buf;
register WK_word packing_mask = TWO_BITS_PACKING_MASK;
/* loop to repeatedly grab one input word and unpack it into
* 4 output words. This loop could be unrolled a little---it's
* designed to be easy to do that.
*/
while (input_next < input_end) {
register WK_word temp = input_next[0];
DEBUG_PRINT_2("Unpacked tags word: %.8x\n", temp);
output_next[0] = temp & packing_mask;
output_next[1] = (temp >> 2) & packing_mask;
output_next[2] = (temp >> 4) & packing_mask;
output_next[3] = (temp >> 6) & packing_mask;
output_next += 4;
input_next++;
}
return output_next;
}
/* unpack four bits consumes any number of words (between input_buf
* and input_end) holding 8 4-bit values per word, and unpacks them
* into twice as many words, with each value in a separate byte.
* (The four-bit values occupy the low halves of the bytes in the
* result).
*/
static WK_word*
WK_unpack_4bits(WK_word *input_buf,
WK_word *input_end,
WK_word *output_buf) {
register WK_word *input_next = input_buf;
register WK_word *output_next = output_buf;
register WK_word packing_mask = FOUR_BITS_PACKING_MASK;
/* loop to repeatedly grab one input word and unpack it into
* 4 output words. This loop should probably be unrolled
* a little---it's designed to be easy to do that.
*/
while (input_next < input_end) {
register WK_word temp = input_next[0];
DEBUG_PRINT_2("Unpacked dictionary indices word: %.8x\n", temp);
output_next[0] = temp & packing_mask;
output_next[1] = (temp >> 4) & packing_mask;
output_next += 2;
input_next++;
}
return output_next;
}
/* unpack_3_tenbits unpacks three 10-bit items from (the low 30 bits of)
* a 32-bit word
*/
static WK_word*
WK_unpack_3_tenbits(WK_word *input_buf,
WK_word *input_end,
WK_word *output_buf) {
register WK_word *input_next = input_buf;
register WK_word *output_next = output_buf;
register WK_word packing_mask = LOW_BITS_MASK;
/* loop to fetch words of input, splitting each into three
* words of output with 10 meaningful low bits. This loop
* probably ought to be unrolled and maybe coiled
*/
while (input_next < input_end) {
register WK_word temp = input_next[0];
output_next[0] = temp & packing_mask;
output_next[1] = (temp >> 10) & packing_mask;
output_next[2] = temp >> 20;
input_next++;
output_next += 3;
}
return output_next;
}
/*********************************************************************
* WKdm_decompress --- THE DECOMPRESSOR
* Expects WORD pointers to the source and destination buffers
* and a page size in words. The page size had better be 1024 unless
* somebody finds the places that are dependent on the page size and
* fixes them
*/
void
WKdm_decompress (WK_word* src_buf,
WK_word* dest_buf,
__unused unsigned int words)
{
DictionaryElement dictionary[DICTIONARY_SIZE];
/* arrays that hold output data in intermediate form during modeling */
/* and whose contents are packed into the actual output after modeling */
/* sizes of these arrays should be increased if you want to compress
* pages larger than 4KB
*/
WK_word tempTagsArray[300]; /* tags for everything */
WK_word tempQPosArray[300]; /* queue positions for matches */
WK_word tempLowBitsArray[1200]; /* low bits for partial matches */
PRELOAD_DICTIONARY;
#ifdef WK_DEBUG
printf("\nIn DECOMPRESSOR\n");
printf("tempTagsArray is at %u\n", (unsigned long int) tempTagsArray);
printf("tempQPosArray is at %u\n", (unsigned long int) tempQPosArray);
printf("tempLowBitsArray is at %u\n", (unsigned long int) tempLowBitsArray);
printf(" first four words of source buffer are:\n");
printf(" %u\n %u\n %u\n %u\n",
src_buf[0], src_buf[1], src_buf[2], src_buf[3]);
{ int i;
WK_word *arr =(src_buf + TAGS_AREA_OFFSET + (PAGE_SIZE_IN_WORDS / 16));
printf(" first 20 full patterns are: \n");
for (i = 0; i < 20; i++) {
printf(" %d", arr[i]);
}
printf("\n");
}
#endif
WK_unpack_2bits(TAGS_AREA_START(src_buf),
TAGS_AREA_END(src_buf),
tempTagsArray);
#ifdef WK_DEBUG
{ int i;
char* arr = (char *) tempTagsArray;
printf(" first 200 tags are: \n");
for (i = 0; i < 200; i++) {
printf(" %d", arr[i]);
}
printf("\n");
}
#endif
WK_unpack_4bits(QPOS_AREA_START(src_buf),
QPOS_AREA_END(src_buf),
tempQPosArray);
#ifdef WK_DEBUG
{ int i;
char* arr = (char *) tempQPosArray;
printf(" first 200 queue positions are: \n");
for (i = 0; i < 200; i++) {
printf(" %d", arr[i]);
}
printf("\n");
}
#endif
WK_unpack_3_tenbits(LOW_BITS_AREA_START(src_buf),
LOW_BITS_AREA_END(src_buf),
tempLowBitsArray);
#ifdef WK_DEBUG
printf("AFTER UNPACKING, about to enter main block \n");
#endif
{
register char *next_tag = (char *) tempTagsArray;
char *tags_area_end =
((char *) tempTagsArray) + PAGE_SIZE_IN_WORDS;
char *next_q_pos = (char *) tempQPosArray;
WK_word *next_low_bits = tempLowBitsArray;
WK_word *next_full_word = FULL_WORD_AREA_START(src_buf);
WK_word *next_output = dest_buf;
#ifdef WK_DEBUG
printf("next_output is %u\n", next_output);
printf("next_tag is %u \n", next_tag);
printf("tags_area_end is %u\n", tags_area_end);
printf("next_q_pos is %u\n", next_q_pos);
printf("next_low_bits is %u\n", next_low_bits);
printf("next_full_word is %u\n", next_full_word);
#endif
/* this loop should probably be unrolled. Maybe we should unpack
* as 4 bit values, giving two consecutive tags, and switch on
* that 16 ways to decompress 2 words at a whack
*/
while (next_tag < tags_area_end) {
char tag = next_tag[0];
switch(tag) {
case ZERO_TAG: {
*next_output = 0;
break;
}
case EXACT_TAG: {
WK_word *dict_location = dictionary + *(next_q_pos++);
/* no need to replace dict. entry if matched exactly */
*next_output = *dict_location;
break;
}
case PARTIAL_TAG: {
WK_word *dict_location = dictionary + *(next_q_pos++);
{
WK_word temp = *dict_location;
/* strip out low bits */
temp = ((temp >> NUM_LOW_BITS) << NUM_LOW_BITS);
/* add in stored low bits from temp array */
temp = temp | *(next_low_bits++);
*dict_location = temp; /* replace old value in dict. */
*next_output = temp; /* and echo it to output */
}
break;
}
case MISS_TAG: {
WK_word missed_word = *(next_full_word++);
WK_word *dict_location =
(WK_word *)
(((char *) dictionary) + HASH_TO_DICT_BYTE_OFFSET(missed_word));
*dict_location = missed_word;
*next_output = missed_word;
break;
}
}
next_tag++;
next_output++;
}
#ifdef WK_DEBUG
printf("AFTER DECOMPRESSING\n");
printf("next_output is %u\n", (unsigned long int) next_output);
printf("next_tag is %u\n", (unsigned long int) next_tag);
printf("next_full_word is %u\n", (unsigned long int) next_full_word);
printf("next_q_pos is %u\n", (unsigned long int) next_q_pos);
#endif
}
}
branches/rewrite/i386/boot2/resume.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
* resume.c
*
*
* Created by mackerintel on 1/22/09.
* Copyright 2009 mackerintel. All rights reserved.
*
*/
#include "saio_internal.h"
#include "libsa.h"
#include "IOHibernatePrivate.h"
#include "memory.h"
#include "bootstruct.h"
#include "boot.h"
#include "pci.h"
extern int previewTotalSectors;
extern int previewLoadedSectors;
extern uint8_t *previewSaveunder;
static unsigned long
getmemorylimit(void)
{
int line;
int i;
MemoryRange *mp = bootInfo->memoryMap;
// Activate and clear page 1
line = 1;
for (i = 0; i < bootInfo->memoryMapCount; i++)
{
if((mp->type == 1) && ((unsigned long)mp->base == 0x100000))
{
return (unsigned long)(mp->base + mp->length);
}
mp++;
}
return 0x10000000;
}
static void WakeKernel(IOHibernateImageHeader * header)
{
uint32_t proc;
unsigned long cnt, newSP;
unsigned long *src, *dst;
unsigned int count;
unsigned int page;
unsigned int compressedSize;
int32_t byteCnt;
u_int32_t lowHalf, highHalf;
u_int32_t sum;
printf("\nWake Kernel!\n");
dst = (unsigned long *) (header->restore1CodePage << 12);
count = header->restore1PageCount;
proc = (header->restore1CodeOffset + ((uint32_t) dst));
newSP = header->restore1StackOffset + (header->restore1CodePage << 12);
src = (unsigned long *) (((u_int32_t) &header->fileExtentMap[0])
+ header->fileExtentMapSize);
sum = 0;
for (page = 0; page < count; page++)
{
compressedSize = 4096;
lowHalf = 1;
highHalf = 0;
for (cnt = 0; cnt < compressedSize; cnt += 0x20) {
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
dst[4] = src[4];
dst[5] = src[5];
dst[6] = src[6];
dst[7] = src[7];
for (byteCnt = 0; byteCnt < 0x20; byteCnt++) {
lowHalf += ((u_int8_t *) dst)[byteCnt];
highHalf += lowHalf;
}
src += 8;
dst += 8;
}
lowHalf %= 65521L;
highHalf %= 65521L;
sum += (highHalf << 16) | lowHalf;
}
header->actualRestore1Sum = sum;
startprog (proc, header);
return;
}
void HibernateBoot(char *image_filename)
{
long long size, imageSize, codeSize, allocSize;
long mem_base;
IOHibernateImageHeader _header;
IOHibernateImageHeader * header = &_header;
long buffer;
size = ReadFileAtOffset (image_filename, header, 0, sizeof(IOHibernateImageHeader));
printf("header read size %x\n", size);
imageSize = header->image1Size;
codeSize = header->restore1PageCount << 12;
if (kIOHibernateHeaderSignature != header->signature)
{
printf ("Incorrect image signature\n");
return;
}
if (header->encryptStart)
{
printf ("Resuming from Encrypted image is unsupported.\n"
"Uncheck \"Use secure virtual memory\" in \"Security\" pane on system preferences.\n"
"Press any key to proceed with normal boot.\n");
getchar();
return;
}
// depends on NVRAM
#if 0
{
uint32_t machineSignature;
size = GetProp(gChosenPH, kIOHibernateMachineSignatureKey,
(char *)&machineSignature, sizeof(machineSignature));
if (size != sizeof(machineSignature)) machineSignature = 0;
if (machineSignature != header->machineSignature)
break;
}
#endif
allocSize = imageSize + ((4095 + sizeof(hibernate_graphics_t)) & ~4095);
mem_base = getmemorylimit() - allocSize;//TODO: lower this
printf("mem_base %x\n", mem_base);
// Rek : hibernate fix
if (!((long long)mem_base+allocSize<1024*bootInfo->extmem+0x100000))
{
printf ("Not enough space to restore image. Press any key to proceed with normal boot.\n");
getchar();
return;
}
bcopy(header, (void *) mem_base, sizeof(IOHibernateImageHeader));
header = (IOHibernateImageHeader *) mem_base;
imageSize -= sizeof(IOHibernateImageHeader);
buffer = (long)(header + 1);
if (header->previewSize)
{
uint64_t preview_offset = header->fileExtentMapSize - sizeof(header->fileExtentMap) + codeSize;
uint8_t progressSaveUnder[kIOHibernateProgressCount][kIOHibernateProgressSaveUnderSize];
ReadFileAtOffset (image_filename, (char *)buffer, sizeof(IOHibernateImageHeader), preview_offset+header->previewSize);
drawPreview ((void *)(long)(buffer+preview_offset + header->previewPageListSize), &(progressSaveUnder[0][0]));
previewTotalSectors = (imageSize-(preview_offset+header->previewSize))/512;
previewLoadedSectors = 0;
previewSaveunder = &(progressSaveUnder[0][0]);
if (preview_offset+header->previewSize<imageSize)
ReadFileAtOffset (image_filename, (char *)(long)(buffer+preview_offset+header->previewSize),
sizeof(IOHibernateImageHeader)+preview_offset+header->previewSize,
imageSize-(preview_offset+header->previewSize));
previewTotalSectors = 0;
previewLoadedSectors = 0;
previewSaveunder = 0;
#if 0
AsereBLN:
check_vga_nvidia() didn't work as expected (recursion level > 0 & return value).
Unforutnaltely I cannot find a note why to switch back to text mode for nVidia cards only
and because it check_vga_nvidia does not work (cards normally are behind a bridge) I will
remove it completely
setVideoMode( VGA_TEXT_MODE, 0 );
#endif
}
else
ReadFileAtOffset (image_filename, (char *)buffer, sizeof(IOHibernateImageHeader), imageSize);
// Depends on NVRAM
#if 0
if (header->encryptStart) {
// decryption data
static const unsigned char first_iv[AES_BLOCK_SIZE]
= { 0xa3, 0x63, 0x65, 0xa9, 0x0b, 0x71, 0x7b, 0x1c,
0xdf, 0x9e, 0x5f, 0x32, 0xd7, 0x61, 0x63, 0xda };
hibernate_cryptvars_t _cryptvars;
hibernate_cryptvars_t * cryptvars = &_cryptvars;
aes_decrypt_key(&decryptkey,
decryptkeysize,
&cryptvars->ctx.decrypt);
// set the vector for the following decryptions
bcopy(((uint8_t *) header) + header->image1Size - AES_BLOCK_SIZE,
&cryptvars->aes_iv[0], AES_BLOCK_SIZE);
// decrypt the buffer
uint32_t len = (uint32_t)(header->image1Size - header->encryptStart);
aes_decrypt_cbc(((uint8_t *) header) + header->encryptStart,
&first_iv[0],
len >> 4,
((uint8_t *) header) + header->encryptStart,
&cryptvars->ctx.decrypt);
bzero(&cryptvars->aes_iv[0], sizeof(cryptvars));
bzero(&decryptkey, sizeof(decryptkey));
}
#endif
WakeKernel(header);
}
branches/rewrite/i386/boot2/WKdm.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
/* direct-mapped partial matching compressor with simple 22/10 split
*
* Compresses buffers using a dictionary based match and partial match
* (high bits only or full match) scheme.
*
* Paul Wilson -- wilson@cs.utexas.edu
* Scott F. Kaplan -- sfkaplan@cs.utexas.edu
* September 1997
*/
/* compressed output format, in memory order
* 1. a four-word HEADER containing four one-word values:
* i. a one-word code saying what algorithm compressed the data
* ii. an integer WORD offset into the page saying
* where the queue position area starts
* iii. an integer WORD offset into the page saying where
* the low-bits area starts
* iv. an integer WORD offset into the page saying where the
* low-bits area ends
*
* 2. a 64-word TAGS AREA holding one two-bit tag for each word in
* the original (1024-word) page, packed 16 per word
*
* 3. a variable-sized FULL WORDS AREA (always word aligned and an
* integral number of words) holding full-word patterns that
* were not in the dictionary when encoded (i.e., dictionary misses)
*
* 4. a variable-sized QUEUE POSITIONS AREA (always word aligned and
* an integral number of words) holding four-bit queue positions,
* packed eight per word.
*
* 5. a variable-sized LOW BITS AREA (always word aligned and an
* integral number of words) holding ten-bit low-bit patterns
* (from partial matches), packed three per word.
*/
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================ */
/* Included files */
//#include <stdio.h>
//#include <unistd.h>
//#include <math.h>
//#include <strings.h>
typedef unsigned long WK_word;
/* at the moment we have dependencies on the page size. That should
* be changed to work for any power-of-two size that's at least 16
* words, or something like that
*/
#define PAGE_SIZE_IN_WORDS 1024
#define PAGE_SIZE_IN_BYTES 4096
#define DICTIONARY_SIZE 16
/*
* macros defining the basic layout of stuff in a page
*/
#define HEADER_SIZE_IN_WORDS 4
#define TAGS_AREA_OFFSET 4
#define TAGS_AREA_SIZE 64
/* the next few are used during compression to write the header */
#define SET_QPOS_AREA_START(compr_dest_buf,qpos_start_addr) \
(compr_dest_buf[1] = qpos_start_addr - compr_dest_buf)
#define SET_LOW_BITS_AREA_START(compr_dest_buf,lb_start_addr) \
(compr_dest_buf[2] = lb_start_addr - compr_dest_buf)
#define SET_LOW_BITS_AREA_END(compr_dest_buf,lb_end_addr) \
(compr_dest_buf[3] = lb_end_addr - compr_dest_buf)
/* the next few are only use during decompression to read the header */
#define TAGS_AREA_START(decomp_src_buf) \
(decomp_src_buf + TAGS_AREA_OFFSET)
#define TAGS_AREA_END(decomp_src_buf) \
(TAGS_AREA_START(decomp_src_buf) + TAGS_AREA_SIZE)
#define FULL_WORD_AREA_START(the_buf) TAGS_AREA_END(the_buf)
#define QPOS_AREA_START(decomp_src_buf) \
(decomp_src_buf + decomp_src_buf[1])
#define LOW_BITS_AREA_START(decomp_src_buf) \
(decomp_src_buf + (decomp_src_buf[2]))
#define QPOS_AREA_END(the_buf) LOW_BITS_AREA_START(the_buf)
#define LOW_BITS_AREA_END(decomp_src_buf) \
(decomp_src_buf + (decomp_src_buf[3]))
/* ============================================================ */
/* Types and structures */
/* A structure to store each element of the dictionary. */
typedef WK_word DictionaryElement;
/* ============================================================ */
/* Misc constants */
#define BITS_PER_WORD 32
#define BYTES_PER_WORD 4
#define NUM_LOW_BITS 10
#define LOW_BITS_MASK 0x3FF
#define ALL_ONES_MASK 0xFFFFFFFF
#define TWO_BITS_PACKING_MASK 0x03030303
#define FOUR_BITS_PACKING_MASK 0x0F0F0F0F
#define TEN_LOW_BITS_MASK 0x000003FF
#define TWENTY_TWO_HIGH_BITS_MASK 0xFFFFFC00
/* Tag values. NOTE THAT CODE MAY DEPEND ON THE NUMBERS USED.
* Check for conditionals doing arithmetic on these things
* before changing them
*/
#define ZERO_TAG 0x0
#define PARTIAL_TAG 0x1
#define MISS_TAG 0x2
#define EXACT_TAG 0x3
#define BITS_PER_BYTE 8
/* ============================================================ */
/* Global macros */
/* Shift out the low bits of a pattern to give the high bits pattern.
The stripped patterns are used for initial tests of partial
matches. */
#define HIGH_BITS(word_pattern) (word_pattern >> NUM_LOW_BITS)
/* String the high bits of a pattern so the low order bits can
be included in an encoding of a partial match. */
#define LOW_BITS(word_pattern) (word_pattern & LOW_BITS_MASK)
#if defined DEBUG_WK
#define DEBUG_PRINT_1(string) printf (string)
#define DEBUG_PRINT_2(string,value) printf(string, value)
#else
#define DEBUG_PRINT_1(string)
#define DEBUG_PRINT_2(string, value)
#endif
/* Set up the dictionary before performing compression or
decompression. Each element is loaded with some value, the
high-bits version of that value, and a next pointer. */
#define PRELOAD_DICTIONARY { \
dictionary[0] = 1; \
dictionary[1] = 1; \
dictionary[2] = 1; \
dictionary[3] = 1; \
dictionary[4] = 1; \
dictionary[5] = 1; \
dictionary[6] = 1; \
dictionary[7] = 1; \
dictionary[8] = 1; \
dictionary[9] = 1; \
dictionary[10] = 1; \
dictionary[11] = 1; \
dictionary[12] = 1; \
dictionary[13] = 1; \
dictionary[14] = 1; \
dictionary[15] = 1; \
}
/* these are the constants for the hash function lookup table.
* Only zero maps to zero. The rest of the tabale is the result
* of appending 17 randomizations of the multiples of 4 from
* 4 to 56. Generated by a Scheme script in hash.scm.
*/
#define HASH_LOOKUP_TABLE_CONTENTS { \
0, 52, 8, 56, 16, 12, 28, 20, 4, 36, 48, 24, 44, 40, 32, 60, \
8, 12, 28, 20, 4, 60, 16, 36, 24, 48, 44, 32, 52, 56, 40, 12, \
8, 48, 16, 52, 60, 28, 56, 32, 20, 24, 36, 40, 44, 4, 8, 40, \
60, 32, 20, 44, 4, 36, 52, 24, 16, 56, 48, 12, 28, 16, 8, 40, \
36, 28, 32, 12, 4, 44, 52, 20, 24, 48, 60, 56, 40, 48, 8, 32, \
28, 36, 4, 44, 20, 56, 60, 24, 52, 16, 12, 12, 4, 48, 20, 8, \
52, 16, 60, 24, 36, 44, 28, 56, 40, 32, 36, 20, 24, 60, 40, 44, \
52, 16, 32, 4, 48, 8, 28, 56, 12, 28, 32, 40, 52, 36, 16, 20, \
48, 8, 4, 60, 24, 56, 44, 12, 8, 36, 24, 28, 16, 60, 20, 56, \
32, 40, 48, 12, 4, 44, 52, 44, 40, 12, 56, 8, 36, 24, 60, 28, \
48, 4, 32, 20, 16, 52, 60, 12, 24, 36, 8, 4, 16, 56, 48, 44, \
40, 52, 32, 20, 28, 32, 12, 36, 28, 24, 56, 40, 16, 52, 44, 4, \
20, 60, 8, 48, 48, 52, 12, 20, 32, 44, 36, 28, 4, 40, 24, 8, \
56, 60, 16, 36, 32, 8, 40, 4, 52, 24, 44, 20, 12, 28, 48, 56, \
16, 60, 4, 52, 60, 48, 20, 16, 56, 44, 24, 8, 40, 12, 32, 28, \
36, 24, 32, 12, 4, 20, 16, 60, 36, 28, 8, 52, 40, 48, 44, 56 \
}
#define HASH_TO_DICT_BYTE_OFFSET(pattern) \
(hashLookupTable[((pattern) >> 10) & 0xFF])
extern const char hashLookupTable[];
/* EMIT... macros emit bytes or words into the intermediate arrays
*/
#define EMIT_BYTE(fill_ptr, byte_value) {*fill_ptr = byte_value; fill_ptr++;}
#define EMIT_WORD(fill_ptr,word_value) {*fill_ptr = word_value; fill_ptr++;}
/* RECORD... macros record the results of modeling in the intermediate
* arrays
*/
#define RECORD_ZERO { EMIT_BYTE(next_tag,ZERO_TAG); }
#define RECORD_EXACT(queue_posn) EMIT_BYTE(next_tag,EXACT_TAG); \
EMIT_BYTE(next_qp,(queue_posn));
#define RECORD_PARTIAL(queue_posn,low_bits_pattern) { \
EMIT_BYTE(next_tag,PARTIAL_TAG); \
EMIT_BYTE(next_qp,(queue_posn)); \
EMIT_WORD(next_low_bits,(low_bits_pattern)) }
#define RECORD_MISS(word_pattern) EMIT_BYTE(next_tag,MISS_TAG); \
EMIT_WORD(next_full_patt,(word_pattern));
void
WKdm_decompress (WK_word* src_buf,
WK_word* dest_buf,
unsigned int words);
unsigned int
WKdm_compress (WK_word* src_buf,
WK_word* dest_buf,
unsigned int num_input_words);
#ifdef __cplusplus
} /* extern "C" */
#endif
branches/rewrite/i386/boot2/bmdecompress.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/*
* Copyright (c) 1995-2002 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* The contents of this file constitute Original Code as defined in and
* are subject to the Apple Public Source License Version 1.1 (the
* "License"). You may not use this file except in compliance with the
* License. Please obtain a copy of the License at
* http://www.apple.com/publicsource and read it before using this file.
*
* This Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#include "libsa.h"
static void
PreviewDecompress16(uint32_t * compressBuffer,
uint32_t width, uint32_t height, uint32_t row,
uint16_t * output)
{
int i, j;
uint32_t * input;
uint16_t * sc0 = malloc((width+2) * sizeof(uint16_t));
uint16_t * sc1 = malloc((width+2) * sizeof(uint16_t));
uint16_t * sc2 = malloc((width+2) * sizeof(uint16_t));
uint16_t * sc3 = malloc((width+2) * sizeof(uint16_t));
uint32_t sr0, sr1, sr2, sr3;
bzero(sc0, (width+2) * sizeof(uint16_t));
bzero(sc1, (width+2) * sizeof(uint16_t));
bzero(sc2, (width+2) * sizeof(uint16_t));
bzero(sc3, (width+2) * sizeof(uint16_t));
uint32_t tmp1, tmp2, out;
for (j = 0; j < (height + 2); j++)
{
input = compressBuffer;
if (j < height)
input += j;
else
input += height - 1;
input = (uint32_t *)(input[3] + ((uint8_t *)compressBuffer));
uint32_t data = 0, repeat = 0, fetch = 0, count = 0;
sr0 = sr1 = sr2 = sr3 = 0;
for (i = 0; i < (width + 2); i++)
{
if (i < width)
{
if (!count)
{
count = *input++;
repeat = (count & 0xff000000);
count ^= repeat;
fetch = true;
}
else
fetch = (0 == repeat);
count--;
if (fetch)
{
data = *((uint16_t *)input);
(*((uint16_t *)input))++;
// grayscale
// srgb 13933, 46871, 4732
// ntsc 19595, 38470, 7471
data = 13933 * (0x1f & (data >> 10))
+ 46871 * (0x1f & (data >> 5))
+ 4732 * (0x1f & data);
data >>= 13;
// 70% white, 30 % black
data *= 19661;
data += (103 << 16);
data >>= 16;
}
}
// gauss blur
tmp2 = sr0 + data;
sr0 = data;
tmp1 = sr1 + tmp2;
sr1 = tmp2;
tmp2 = sr2 + tmp1;
sr2 = tmp1;
tmp1 = sr3 + tmp2;
sr3 = tmp2;
tmp2 = sc0[i] + tmp1;
sc0[i] = tmp1;
tmp1 = sc1[i] + tmp2;
sc1[i] = tmp2;
tmp2 = sc2[i] + tmp1;
sc2[i] = tmp1;
out = (128 + sc3[i] + tmp2) >> 11;
sc3[i] = tmp2;
out &= 0x1f;
if ((i > 1) && (j > 1))
output[i-2] = out | (out << 5) | (out << 10);
}
if (j > 1)
output += row;
}
free(sc3);
free(sc2);
free(sc1);
free(sc0);
}
static void
PreviewDecompress32(uint32_t * compressBuffer,
uint32_t width, uint32_t height, uint32_t row,
uint32_t * output)
{
int i, j;
uint32_t * input;
uint16_t * sc0 = malloc((width+2) * sizeof(uint16_t));
uint16_t * sc1 = malloc((width+2) * sizeof(uint16_t));
uint16_t * sc2 = malloc((width+2) * sizeof(uint16_t));
uint16_t * sc3 = malloc((width+2) * sizeof(uint16_t));
uint32_t sr0, sr1, sr2, sr3;
bzero(sc0, (width+2) * sizeof(uint16_t));
bzero(sc1, (width+2) * sizeof(uint16_t));
bzero(sc2, (width+2) * sizeof(uint16_t));
bzero(sc3, (width+2) * sizeof(uint16_t));
uint32_t tmp1, tmp2, out;
for (j = 0; j < (height + 2); j++)
{
input = compressBuffer;
if (j < height)
input += j;
else
input += height - 1;
input = (uint32_t *)(input[3] + ((uint8_t *)compressBuffer));
uint32_t data = 0, repeat = 0, fetch = 0, count = 0;
sr0 = sr1 = sr2 = sr3 = 0;
for (i = 0; i < (width + 2); i++)
{
if (i < width)
{
if (!count)
{
count = *input++;
repeat = (count & 0xff000000);
count ^= repeat;
fetch = true;
}
else
fetch = (0 == repeat);
count--;
if (fetch)
{
data = *input++;
// grayscale
// srgb 13933, 46871, 4732
// ntsc 19595, 38470, 7471
data = 13933 * (0xff & (data >> 24))
+ 46871 * (0xff & (data >> 16))
+ 4732 * (0xff & data);
data >>= 16;
// 70% white, 30 % black
data *= 19661;
data += (103 << 16);
data >>= 16;
}
}
// gauss blur
tmp2 = sr0 + data;
sr0 = data;
tmp1 = sr1 + tmp2;
sr1 = tmp2;
tmp2 = sr2 + tmp1;
sr2 = tmp1;
tmp1 = sr3 + tmp2;
sr3 = tmp2;
tmp2 = sc0[i] + tmp1;
sc0[i] = tmp1;
tmp1 = sc1[i] + tmp2;
sc1[i] = tmp2;
tmp2 = sc2[i] + tmp1;
sc2[i] = tmp1;
out = (128 + sc3[i] + tmp2) >> 8;
sc3[i] = tmp2;
out &= 0xff;
if ((i > 1) && (j > 1))
output[i-2] = out | (out << 8) | (out << 16);
}
if (j > 1)
output += row;
}
free(sc3);
free(sc2);
free(sc1);
free(sc0);
}
void *
DecompressData(void *srcbase, int *dw, int *dh, int *bitsPerPixel)
{
uint32_t * src = (uint32_t *) srcbase;
void * ret;
*bitsPerPixel = 8 * ((int) src[0]);
*dw = (int) src[1];
*dh = (int) src[2];
ret = malloc ((*dw * *dh * *bitsPerPixel)/ 8);
switch(*bitsPerPixel)
{
case 32:
PreviewDecompress32((uint32_t *)srcbase, *dw, *dh, *dw, ret);
return ret;
case 16:
PreviewDecompress16((uint32_t *)srcbase, *dw, *dh, *dw, ret);
return ret;
default:
return 0;
}
}
branches/rewrite/i386/boot2/gui.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
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
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
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
1752
1753
1754
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
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
/*
* gui.c
*
*
* Created by Jasmin Fazlic on 18.12.08.
* Copyright 2008/09 Jasmin Fazlic All rights reserved.
* Copyright 2008/09 iNDi All rights reserved.
*
*/
#include "gui.h"
#include "appleboot.h"
#include "vers.h"
#define IMG_REQUIRED -1
#define THEME_NAME_DEFAULT"Default"
static const char *theme_name = THEME_NAME_DEFAULT;
#ifdef CONFIG_EMBED_THEME
#include "art.h"
#endif
#define LOADPNG(img, alt_img) if (loadThemeImage(#img, alt_img) != 0) { return 1; }
#define VIDEO(x) (bootArgs->Video.v_ ## x)
#define vram VIDEO(baseAddr)
int lasttime = 0; // we need this for animating maybe
/*
* ATTENTION: the enum and the following array images[] MUST match !!!
*/
enum {
iBackground = 0,
iLogo,
iDeviceGeneric,
iDeviceGeneric_o,
iDeviceHFS,
iDeviceHFS_o,
iDeviceHFSRAID,
iDeviceHFSRAID_o,
iDeviceEXT3,
iDeviceEXT3_o,
iDeviceFAT,
iDeviceFAT_o,
iDeviceFAT16,
iDeviceFAT16_o,
iDeviceFAT32,
iDeviceFAT32_o,
iDeviceNTFS,
iDeviceNTFS_o,
iDeviceCDROM,
iDeviceCDROM_o,
iSelection,
iDeviceScrollPrev,
iDeviceScrollNext,
iMenuBoot,
iMenuVerbose,
iMenuIgnoreCaches,
iMenuSingleUser,
iMenuMemoryInfo,
iMenuVideoInfo,
iMenuHelp,
iMenuVerboseDisabled,
iMenuIgnoreCachesDisabled,
iMenuSingleUserDisabled,
iMenuSelection,
iProgressBar,
iProgressBarBackground,
iTextScrollPrev,
iTextScrollNext,
iFontConsole,
iFontSmall,
};
image_t images[] = {
{.name = "background", .image = NULL},
{.name = "logo", .image = NULL},
{.name = "device_generic", .image = NULL},
{.name = "device_generic_o", .image = NULL},
{.name = "device_hfsplus", .image = NULL},
{.name = "device_hfsplus_o", .image = NULL},
{.name = "device_hfsraid", .image = NULL},
{.name = "device_hfsraid_o", .image = NULL},
{.name = "device_ext3", .image = NULL},
{.name = "device_ext3_o", .image = NULL},
{.name = "device_fat", .image = NULL},
{.name = "device_fat_o", .image = NULL},
{.name = "device_fat16", .image = NULL},
{.name = "device_fat16_o", .image = NULL},
{.name = "device_fat32", .image = NULL},
{.name = "device_fat32_o", .image = NULL},
{.name = "device_ntfs", .image = NULL},
{.name = "device_ntfs_o", .image = NULL},
{.name = "device_cdrom", .image = NULL},
{.name = "device_cdrom_o", .image = NULL},
{.name = "device_selection", .image = NULL},
{.name = "device_scroll_prev", .image = NULL},
{.name = "device_scroll_next", .image = NULL},
{.name = "menu_boot", .image = NULL},
{.name = "menu_verbose", .image = NULL},
{.name = "menu_ignore_caches", .image = NULL},
{.name = "menu_single_user", .image = NULL},
{.name = "menu_memory_info", .image = NULL},
{.name = "menu_video_info", .image = NULL},
{.name = "menu_help", .image = NULL},
{.name = "menu_verbose_disabled", .image = NULL},
{.name = "menu_ignore_caches_disabled", .image = NULL},
{.name = "menu_single_user_disabled", .image = NULL},
{.name = "menu_selection", .image = NULL},
{.name = "progress_bar", .image = NULL},
{.name = "progress_bar_background", .image = NULL},
{.name = "text_scroll_prev", .image = NULL},
{.name = "text_scroll_next", .image = NULL},
{.name = "font_console", .image = NULL},
{.name = "font_small", .image = NULL},
};
int imageCnt = 0;
extern intgDeviceCount;
extern intselectIndex;
extern MenuItem *menuItems;
//char prompt[BOOT_STRING_LEN];
extern char gBootArgs[BOOT_STRING_LEN];
char prompt_text[] = "boot: ";
menuitem_t infoMenuItems[] =
{
{ .text = "Boot" },
{ .text = "Boot Verbose" },
{ .text = "Boot Ignore Caches" },
{ .text = "Boot Single User" },
{ .text = "Memory Info" },
{ .text = "Video Info" },
{ .text = "Help" }
};
int initFont(font_t *font, image_t *image);
void colorFont(font_t *font, uint32_t color);
void makeRoundedCorners(pixmap_t *p);
static int infoMenuSelection = 0;
static int infoMenuItemsCount = sizeof(infoMenuItems)/sizeof(infoMenuItems[0]);
static bool infoMenuNativeBoot = false;
// here we store the used screen resolution
static unsigned long screen_params[4] = {DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, 32, 0};
static int getImageIndexByName(const char *name)
{
int i;
for (i = 0; i < sizeof(images) / sizeof(images[0]); i++)
{
if (strcmp(name, images[i].name) == 0)
return i; // found the name
}
return -1;
}
#ifdef CONFIG_EMBED_THEME
static int getEmbeddedImageIndexByName(const char *name)
{
int upperLimit = sizeof(embeddedImages) / sizeof(embeddedImages[0]) - 1;
int lowerLimit = 0;
int compareIndex = (upperLimit - lowerLimit) >> 1; // Midpoint
int result;
// NOTE: This algorithm assumes that the embedded images are sorted.
// This is currently done using the make file. If the array is
// generated manualy, this *will* fail to work properly.
while((result = strcmp(name, embeddedImages[compareIndex].name)) != 0)
{
if (result > 0)// We need to search a HIGHER index
{
if (compareIndex != lowerLimit)
{
lowerLimit = compareIndex;
}
else
{
return -1;
}
compareIndex = (upperLimit + lowerLimit + 1) >> 1;// Midpoint, round up
}
else // We Need to search a LOWER index
{
if (compareIndex != upperLimit)
{
upperLimit = compareIndex;
}
else
{
return -1;
}
compareIndex = (upperLimit + lowerLimit) >> 1;// Midpoint, round down
}
}
return compareIndex;
}
#endif
static int loadThemeImage(const char *image, int alt_image)
{
chardirspec[256];
int i;
#ifdef CONFIG_EMBED_THEME
int e;
#endif
uint16_twidth;
uint16_theight;
uint8_t*imagedata;
if ((strlen(image) + strlen(theme_name) + 20 ) > sizeof(dirspec)) {
return 1;
}
if ((i = getImageIndexByName(image)) >= 0)
{
if (images[i].image == NULL) {
images[i].image = malloc(sizeof(pixmap_t));
}
sprintf(dirspec, "/Extra/Themes/%s/%s.png", theme_name, image);
width = 0;
height = 0;
imagedata = NULL;
if ((loadPngImage(dirspec, &width, &height, &imagedata)) == 0)
{
images[i].image->width = width;
images[i].image->height = height;
images[i].image->pixels = (pixel_t *)imagedata;
flipRB(images[i].image);
return 0;
}
#ifdef CONFIG_EMBED_THEME
else if ((e = getEmbeddedImageIndexByName(image)) >= 0)
{
unsigned char *embed_data;
unsigned int embed_size;
embed_data = embeddedImages[e].pngdata;
embed_size = *embeddedImages[e].length;
if (loadEmbeddedPngImage(embed_data, embed_size, &width, &height, &imagedata) == 0)
{
images[i].image->width = width;
images[i].image->height = height;
images[i].image->pixels = (pixel_t *)imagedata;
flipRB(images[i].image);
return 0;
}
return 0;
}
#endif
else if (alt_image != IMG_REQUIRED && images[alt_image].image->pixels != NULL)
{
// Using the passed alternate image for non-mandatory images.
// We don't clone the already existing pixmap, but using its properties instead!
images[i].image->width = images[alt_image].image->width;
images[i].image->height = images[alt_image].image->height;
images[i].image->pixels = images[alt_image].image->pixels;
return 0;
}
else
{
#ifndef CONFIG_EMBED_THEME
printf("ERROR: GUI: could not open '%s/%s.png'!\n", theme_name, image);
sleep(2);
#endif
return 1;
}
}
return 1;
}
static int loadGraphics(void)
{
LOADPNG(background, IMG_REQUIRED);
LOADPNG(logo, IMG_REQUIRED);
LOADPNG(device_generic, IMG_REQUIRED);
LOADPNG(device_generic_o, iDeviceGeneric);
LOADPNG(device_hfsplus, iDeviceGeneric);
LOADPNG(device_hfsplus_o, iDeviceHFS);
LOADPNG(device_hfsraid, iDeviceGeneric);
LOADPNG(device_hfsraid_o, iDeviceHFSRAID);
LOADPNG(device_ext3, iDeviceGeneric);
LOADPNG(device_ext3_o, iDeviceEXT3);
LOADPNG(device_fat, iDeviceGeneric);
LOADPNG(device_fat_o, iDeviceFAT);
LOADPNG(device_fat16, iDeviceFAT);
LOADPNG(device_fat16_o, iDeviceFAT_o);
LOADPNG(device_fat32, iDeviceFAT);
LOADPNG(device_fat32_o, iDeviceFAT_o);
LOADPNG(device_ntfs, iDeviceGeneric);
LOADPNG(device_ntfs_o, iDeviceNTFS);
LOADPNG(device_cdrom, iDeviceGeneric);
LOADPNG(device_cdrom_o, iDeviceCDROM);
LOADPNG(device_selection, IMG_REQUIRED);
LOADPNG(device_scroll_prev, IMG_REQUIRED);
LOADPNG(device_scroll_next, IMG_REQUIRED);
LOADPNG(menu_boot, IMG_REQUIRED);
LOADPNG(menu_verbose, IMG_REQUIRED);
LOADPNG(menu_ignore_caches, IMG_REQUIRED);
LOADPNG(menu_single_user, IMG_REQUIRED);
LOADPNG(menu_memory_info, IMG_REQUIRED);
LOADPNG(menu_video_info, IMG_REQUIRED);
LOADPNG(menu_help, IMG_REQUIRED);
LOADPNG(menu_verbose_disabled, IMG_REQUIRED);
LOADPNG(menu_ignore_caches_disabled, IMG_REQUIRED);
LOADPNG(menu_single_user_disabled, IMG_REQUIRED);
LOADPNG(menu_selection, IMG_REQUIRED);
LOADPNG(progress_bar, IMG_REQUIRED);
LOADPNG(progress_bar_background, IMG_REQUIRED);
LOADPNG(text_scroll_prev, IMG_REQUIRED);
LOADPNG(text_scroll_next, IMG_REQUIRED);
LOADPNG(font_console, IMG_REQUIRED);
LOADPNG(font_small, IMG_REQUIRED);
initFont( &font_console, &images[iFontConsole]);
initFont( &font_small, &images[iFontSmall]);
return 0;
}
pixmap_t *getCroppedPixmapAtPosition( pixmap_t *from, position_t pos, uint16_t width, uint16_t height )
{
pixmap_t *cropped = malloc( sizeof( pixmap_t ) );
if( !cropped )
return 0;
cropped->pixels = malloc( width * height * 4 );
if ( !cropped->pixels )
return 0;
cropped->width = width;
cropped->height = height;
int destx = 0, desty = 0;
int srcx = pos.x, srcy = pos.y;
for( ; desty < height; desty++, srcy++)
{
for( destx = 0, srcx = pos.x; destx < width; destx++, srcx++ )
{
pixel( cropped, destx, desty ).value = pixel( from, srcx, srcy ).value;
}
}
return cropped;
}
int createBackBuffer( window_t *window )
{
gui.backbuffer = malloc(sizeof(pixmap_t));
if(!gui.backbuffer)
return 1;
gui.backbuffer->pixels = malloc( window->width * window->height * 4 );
if(!gui.backbuffer->pixels)
{
free(gui.backbuffer);
gui.backbuffer = 0;
return 1;
}
gui.backbuffer->width = gui.screen.width;
gui.backbuffer->height = gui.screen.height;
return 0;
}
int createWindowBuffer( window_t *window )
{
window->pixmap = malloc(sizeof(pixmap_t));
if(!window->pixmap)
return 1;
window->pixmap->pixels = malloc( window->width * window->height * 4 );
if(!window->pixmap->pixels)
{
free(window->pixmap);
window->pixmap = 0;
return 1;
}
window->pixmap->width = window->width;
window->pixmap->height = window->height;
return 0;
}
int freeWindowBuffer( window_t *window )
{
if (window->pixmap && window->pixmap->pixels)
{
free(window->pixmap->pixels);
free(window->pixmap);
return 0;
}
return 1;
}
void fillPixmapWithColor(pixmap_t *pm, uint32_t color)
{
int x,y;
// fill with given color AARRGGBB
for( x=0; x < pm->width; x++ )
for( y=0; y< pm->height; y++)
pixel(pm,x,y).value = color;
}
void drawBackground()
{
// reset text cursor
gui.screen.cursor.x = gui.screen.hborder;
gui.screen.cursor.y = gui.screen.vborder;
fillPixmapWithColor( gui.screen.pixmap, gui.screen.bgcolor);
// draw background.png into background buffer
blend( images[iBackground].image, gui.screen.pixmap, gui.background.pos );
// draw logo.png into background buffer
if (gui.logo.draw)
{
blend( images[iLogo].image, gui.screen.pixmap, gui.logo.pos);
}
memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
}
void setupDeviceList(config_file_t *theme)
{
unsigned int pixel;
intalpha;// transparency level 0 (obligue) - 255 (transparent)
uint32_t color;// color value formatted RRGGBB
int val, len;
const char *string;
if(getIntForKey("devices_max_visible", &val, theme ))
gui.maxdevices = MIN( val, gDeviceCount );
if(getIntForKey("devices_iconspacing", &val, theme ))
gui.devicelist.iconspacing = val;
// check layout for horizontal or vertical
gui.layout = HorizontalLayout;
if(getValueForKey( "devices_layout", &string, &len, theme)) {
if (!strcmp (string, "vertical")) {
gui.layout = VerticalLayout;
}
}
switch (gui.layout) {
case VerticalLayout:
gui.devicelist.height = ((images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->height + images[iDeviceScrollNext].image->height) + gui.devicelist.iconspacing);
gui.devicelist.width = (images[iSelection].image->width + gui.devicelist.iconspacing);
if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , images[iSelection].image->width ) )
gui.devicelist.pos.x = pixel;
if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , gui.devicelist.height ) )
gui.devicelist.pos.y = pixel;
break;
case HorizontalLayout:
default:
gui.devicelist.width = ((images[iSelection].image->width + gui.devicelist.iconspacing) * MIN(gui.maxdevices, gDeviceCount) + (images[iDeviceScrollPrev].image->width + images[iDeviceScrollNext].image->width) + gui.devicelist.iconspacing);
gui.devicelist.height = (images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing);
if(getDimensionForKey("devices_pos_x", &pixel, theme, gui.screen.width , gui.devicelist.width ) )
gui.devicelist.pos.x = pixel;
else
gui.devicelist.pos.x = ( gui.screen.width - gui.devicelist.width ) / 2;
if(getDimensionForKey("devices_pos_y", &pixel, theme, gui.screen.height , images[iSelection].image->height ) )
gui.devicelist.pos.y = pixel;
else
gui.devicelist.pos.y = ( gui.screen.height - gui.devicelist.height ) / 2;
break;
}
if(getColorForKey("devices_bgcolor", &color, theme))
gui.devicelist.bgcolor = (color & 0x00FFFFFF);
if(getIntForKey("devices_transparency", &alpha, theme))
gui.devicelist.bgcolor = gui.devicelist.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
if (gui.devicelist.pixmap)
{
freeWindowBuffer(&gui.devicelist);
createWindowBuffer(&gui.devicelist);
}
}
void loadThemeValues(config_file_t *theme)
{
unsigned int screen_width = gui.screen.width;
unsigned int screen_height = gui.screen.height;
unsigned int pixel;
intalpha;// transparency level 0 (obligue) - 255 (transparent)
uint32_t color;// color value formatted RRGGBB
int val;
/*
* Parse screen parameters
*/
if(getColorForKey("screen_bgcolor", &color, theme ))
gui.screen.bgcolor = (color & 0x00FFFFFF);
if(getIntForKey("screen_textmargin_h", &val, theme))
gui.screen.hborder = MIN( gui.screen.width , val );
if(getIntForKey("screen_textmargin_v", &val, theme))
gui.screen.vborder = MIN( gui.screen.height , val );
/*
* Parse background parameters
*/
if(getDimensionForKey("background_pos_x", &pixel, theme, screen_width , images[iBackground].image->width ) )
gui.background.pos.x = pixel;
if(getDimensionForKey("background_pos_y", &pixel, theme, screen_height , images[iBackground].image->height ) )
gui.background.pos.y = pixel;
/*
* Parse logo parameters
*/
if(getDimensionForKey("logo_pos_x", &pixel, theme, screen_width , images[iLogo].image->width ) )
gui.logo.pos.x = pixel;
if(getDimensionForKey("logo_pos_y", &pixel, theme, screen_height , images[iLogo].image->height ) )
gui.logo.pos.y = pixel;
/*
* Parse progress bar parameters
*/
if(getDimensionForKey("progressbar_pos_x", &pixel, theme, screen_width , 0 ) )
gui.progressbar.pos.x = pixel;
if(getDimensionForKey("progressbar_pos_y", &pixel, theme, screen_height , 0 ) )
gui.progressbar.pos.y = pixel;
/*
* Parse countdown text parameters
*/
if(getDimensionForKey("countdown_pos_x", &pixel, theme, screen_width , 0 ) )
gui.countdown.pos.x = pixel;
if(getDimensionForKey("countdown_pos_y", &pixel, theme, screen_height , 0 ) )
gui.countdown.pos.y = pixel;
/*
* Parse devicelist parameters
*/
setupDeviceList(theme);
/*
* Parse infobox parameters
*/
if(getIntForKey("infobox_width", &val, theme))
gui.infobox.width = MIN( screen_width , val );
if(getIntForKey("infobox_height", &val, theme))
gui.infobox.height = MIN( screen_height , val );
if(getDimensionForKey("infobox_pos_x", &pixel, theme, screen_width , gui.infobox.width ) )
gui.infobox.pos.x = pixel;
if(getDimensionForKey("infobox_pos_y", &pixel, theme, screen_height , gui.infobox.height ) )
gui.infobox.pos.y = pixel;
if(getIntForKey("infobox_textmargin_h", &val, theme))
gui.infobox.hborder = MIN( gui.infobox.width , val );
if(getIntForKey("infobox_textmargin_v", &val, theme))
gui.infobox.vborder = MIN( gui.infobox.height , val );
if(getColorForKey("infobox_bgcolor", &color, theme))
gui.infobox.bgcolor = (color & 0x00FFFFFF);
if(getIntForKey("infobox_transparency", &alpha, theme))
gui.infobox.bgcolor = gui.infobox.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
/*
* Parse menu parameters
*/
if(getDimensionForKey("menu_width", &pixel, theme, gui.screen.width , 0 ) )
gui.menu.width = pixel;
else
gui.menu.width = images[iMenuSelection].image->width;
if(getDimensionForKey("menu_height", &pixel, theme, gui.screen.height , 0 ) )
gui.menu.height = pixel;
else
gui.menu.height = (infoMenuItemsCount) * images[iMenuSelection].image->height;
if(getDimensionForKey("menu_pos_x", &pixel, theme, screen_width , gui.menu.width ) )
gui.menu.pos.x = pixel;
if(getDimensionForKey("menu_pos_y", &pixel, theme, screen_height , gui.menu.height ) )
gui.menu.pos.y = pixel;
if(getIntForKey("menu_textmargin_h", &val, theme))
gui.menu.hborder = MIN( gui.menu.width , val );
if(getIntForKey("menu_textmargin_v", &val, theme))
gui.menu.vborder = MIN( gui.menu.height , val );
if(getColorForKey("menu_bgcolor", &color, theme))
gui.menu.bgcolor = (color & 0x00FFFFFF);
if(getIntForKey("menu_transparency", &alpha, theme))
gui.menu.bgcolor = gui.menu.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
/*
* Parse bootprompt parameters
*/
if(getDimensionForKey("bootprompt_width", &pixel, theme, screen_width , 0 ) )
gui.bootprompt.width = pixel;
if(getIntForKey("bootprompt_height", &val, theme))
gui.bootprompt.height = MIN( screen_height , val );
if(getDimensionForKey("bootprompt_pos_x", &pixel, theme, screen_width , gui.bootprompt.width ) )
gui.bootprompt.pos.x = pixel;
if(getDimensionForKey("bootprompt_pos_y", &pixel, theme, screen_height , gui.bootprompt.height ) )
gui.bootprompt.pos.y = pixel;
if(getIntForKey("bootprompt_textmargin_h", &val, theme))
gui.bootprompt.hborder = MIN( gui.bootprompt.width , val );
if(getIntForKey("bootprompt_textmargin_v", &val, theme))
gui.bootprompt.vborder = MIN( gui.bootprompt.height , val );
if(getColorForKey("bootprompt_bgcolor", &color, theme))
gui.bootprompt.bgcolor = (color & 0x00FFFFFF);
if(getIntForKey("bootprompt_transparency", &alpha, theme))
gui.bootprompt.bgcolor = gui.bootprompt.bgcolor | (( 255 - ( alpha & 0xFF) ) << 24);
if(getColorForKey("font_small_color", &color, theme))
gui.screen.font_small_color = (color & 0x00FFFFFF);
if(getColorForKey("font_console_color", &color, theme))
gui.screen.font_console_color = (color & 0x00FFFFFF);
}
int initGUI(void)
{
intval;
intlen;
chardirspec[256];
getValueForKey( "Theme", &theme_name, &len, &bootInfo->bootConfig );
if ((strlen(theme_name) + 27) > sizeof(dirspec)) {
return 1;
}
sprintf(dirspec, "/Extra/Themes/%s/theme.plist", theme_name);
if (loadConfigFile(dirspec, &bootInfo->themeConfig) != 0) {
#ifdef CONFIG_EMBED_THEME
config_file_t*config;
config = &bootInfo->themeConfig;
if (ParseXMLFile((char *)__theme_plist, &config->dictionary) != 0) {
return 1;
}
#else
return 1;
#endif
}
// parse display size parameters
if (getIntForKey("screen_width", &val, &bootInfo->themeConfig) && val > 0) {
screen_params[0] = val;
}
if (getIntForKey("screen_height", &val, &bootInfo->themeConfig) && val > 0) {
screen_params[1] = val;
}
// Initalizing GUI strucutre.
bzero(&gui, sizeof(gui_t));
// find best matching vesa mode for our requested width & height
getGraphicModeParams(screen_params);
// set our screen structure with the mode width & height
gui.screen.width = screen_params[0];
gui.screen.height = screen_params[1];
// load graphics otherwise fail and return
if (loadGraphics() == 0) {
loadThemeValues(&bootInfo->themeConfig);
colorFont(&font_small, gui.screen.font_small_color);
colorFont(&font_console, gui.screen.font_console_color);
// create the screen & window buffers
if (createBackBuffer(&gui.screen) == 0) {
if (createWindowBuffer(&gui.screen) == 0) {
if (createWindowBuffer(&gui.devicelist) == 0) {
if (createWindowBuffer(&gui.bootprompt) == 0) {
if (createWindowBuffer(&gui.infobox) == 0) {
if (createWindowBuffer(&gui.menu) == 0) {
gui.logo.draw = true;
drawBackground();
// lets copy the screen into the back buffer
memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
setVideoMode( GRAPHICS_MODE, 0 );
gui.initialised = true;
return 0;
}
}
}
}
}
}
}
return 1;
}
void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p, bool isSelected)
{
int devicetype;
if( diskIsCDROM(device) )
devicetype = iDeviceCDROM;// Use CDROM icon
else
{
switch (device->part_type)
{
case kPartitionTypeHFS:
// Use HFS or HFSRAID icon depending on bvr flags.
devicetype = (device->flags & kBVFlagBooter) ? iDeviceHFSRAID : iDeviceHFS;
break;
case kPartitionTypeHPFS:
devicetype = iDeviceNTFS;// Use HPFS / NTFS icon
break;
case kPartitionTypeFAT16:
devicetype = iDeviceFAT16;// Use FAT16 icon
break;
case kPartitionTypeFAT32:
devicetype = iDeviceFAT32;// Use FAT32 icon
break;
case kPartitionTypeEXT3:
devicetype = iDeviceEXT3;// Use EXT2/3 icon
break;
default:
devicetype = iDeviceGeneric;// Use Generic icon
break;
}
}
// Draw the selection image and use the next (device_*_o) image for the selected item.
if (isSelected)
{
blend(images[iSelection].image, buffer, centeredAt(images[iSelection].image, p));
devicetype++;
}
// draw icon
blend( images[devicetype].image, buffer, centeredAt( images[devicetype].image, p ));
p.y += (images[iSelection].image->height / 2) + font_console.chars[0]->height;
// draw volume label
drawStrCenteredAt( device->label, &font_small, buffer, p);
}
void drawDeviceList (int start, int end, int selection)
{
int i;
position_t p, p_prev, p_next;
//uint8_tmaxDevices = MIN( gui.maxdevices, menucount );
fillPixmapWithColor( gui.devicelist.pixmap, gui.devicelist.bgcolor);
makeRoundedCorners( gui.devicelist.pixmap);
switch (gui.layout)
{
case VerticalLayout:
p.x = (gui.devicelist.width /2);
p.y = ( ( images[iSelection].image->height / 2 ) + images[iDeviceScrollPrev].image->height + gui.devicelist.iconspacing );
// place scroll indicators at top & bottom edges
p_prev = pos ( gui.devicelist.width / 2 , gui.devicelist.iconspacing );
p_next = pos ( p_prev.x, gui.devicelist.height - gui.devicelist.iconspacing );
break;
default:// use Horizontal layout as the default
case HorizontalLayout:
p.x = (gui.devicelist.width - ( gui.devicelist.width / gui.maxdevices ) * gui.maxdevices ) / 2 + ( images[iSelection].image->width / 2) + images[iDeviceScrollPrev].image->width + gui.devicelist.iconspacing;
p.y = ((gui.devicelist.height - font_console.chars[0]->height ) - images[iSelection].image->height) / 2 + ( images[iSelection].image->height / 2 );
// place scroll indicators at left & right edges
p_prev = pos ( images[iDeviceScrollPrev].image->width / 2 + gui.devicelist.iconspacing / 2, gui.devicelist.height / 2 );
p_next = pos ( gui.devicelist.width - ( images[iDeviceScrollNext].image->width / 2 + gui.devicelist.iconspacing / 2), gui.devicelist.height / 2 );
break;
}
// draw visible device icons
for (i = 0; i < gui.maxdevices; i++)
{
BVRef param = menuItems[start + i].param;
bool isSelected = ((start + i) == selection) ? true : false;
if (isSelected)
{
if (param->flags & kBVFlagNativeBoot)
{
infoMenuNativeBoot = true;
}
else
{
infoMenuNativeBoot = false;
if(infoMenuSelection >= INFOMENU_NATIVEBOOT_START && infoMenuSelection <= INFOMENU_NATIVEBOOT_END)
infoMenuSelection = 0;
}
if(gui.menu.draw)
drawInfoMenuItems();
#if DEBUG
gui.debug.cursor = pos( 10, 100);
dprintf( &gui.screen, "label %s\n", param->label );
dprintf( &gui.screen, "biosdev 0x%x\n", param->biosdev );
dprintf(&gui.screen, "width %d\n", gui.screen.width);
dprintf(&gui.screen, "height %d\n", gui.screen.height);
dprintf( &gui.screen, "type 0x%x\n", param->type );
dprintf( &gui.screen, "flags 0x%x\n", param->flags );
dprintf( &gui.screen, "part_no %d\n", param->part_no );
dprintf( &gui.screen, "part_boff 0x%x\n", param->part_boff );
dprintf( &gui.screen, "part_type 0x%x\n", param->part_type );
dprintf( &gui.screen, "bps 0x%x\n", param->bps );
dprintf( &gui.screen, "name %s\n", param->name );
dprintf( &gui.screen, "type_name %s\n", param->type_name );
dprintf( &gui.screen, "modtime %d\n", param->modTime );
#endif
}
drawDeviceIcon( param, gui.devicelist.pixmap, p, isSelected);
if (gui.layout == HorizontalLayout)
{
p.x += images[iSelection].image->width + gui.devicelist.iconspacing;
}
if (gui.layout == VerticalLayout)
{
p.y += ( images[iSelection].image->height + font_console.chars[0]->height + gui.devicelist.iconspacing );
}
}
// draw prev indicator
if(start)
blend( images[iDeviceScrollPrev].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollPrev].image, p_prev ) );
// draw next indicator
if( end < gDeviceCount - 1 )
blend( images[iDeviceScrollNext].image, gui.devicelist.pixmap, centeredAt( images[iDeviceScrollNext].image, p_next ) );
gui.redraw = true;
updateVRAM();
}
void clearGraphicBootPrompt()
{
// clear text buffer
//prompt[0] = '\0';
//prompt_pos=0;
if(gui.bootprompt.draw == true )
{
gui.bootprompt.draw = false;
gui.redraw = true;
// this causes extra frames to be drawn
//updateVRAM();
}
return;
}
void updateGraphicBootPrompt()
{
fillPixmapWithColor( gui.bootprompt.pixmap, gui.bootprompt.bgcolor);
makeRoundedCorners( gui.bootprompt.pixmap);
position_t p_text = pos( gui.bootprompt.hborder , ( ( gui.bootprompt.height - font_console.chars[0]->height) ) / 2 );
// print the boot prompt text
drawStr(prompt_text, &font_console, gui.bootprompt.pixmap, p_text);
// get the position of the end of the boot prompt text to display user input
position_t p_prompt = pos( p_text.x + ( ( strlen(prompt_text) ) * font_console.chars[0]->width ), p_text.y );
drawStr( gBootArgs, &font_console, gui.bootprompt.pixmap, p_prompt);
gui.menu.draw = false;
gui.bootprompt.draw = true;
gui.redraw = true;
updateVRAM();
return;
}
inline
void vramwrite (void *data, int width, int height)
{
if (VIDEO (depth) == 32 && VIDEO (rowBytes) == gui.backbuffer->width * 4)
memcpy((uint8_t *)vram, gui.backbuffer->pixels, VIDEO (rowBytes)*VIDEO (height));
else
{
uint32_t r, g, b;
int i, j;
for (i = 0; i < VIDEO (height); i++)
for (j = 0; j < VIDEO (width); j++)
{
b = ((uint8_t *) data)[4*i*width + 4*j];
g = ((uint8_t *) data)[4*i*width + 4*j + 1];
r = ((uint8_t *) data)[4*i*width + 4*j + 2];
switch (VIDEO (depth))
{
case 32:
*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*4) = (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
break;
case 24:
*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3) = ((*(uint32_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*3))&0xff000000)
| (b&0xff) | ((g&0xff)<<8) | ((r&0xff)<<16);
break;
case 16:
// Somehow 16-bit is always 15-bits really
//*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xfc)<<3) | ((r&0xf8)<<8);
//break;
case 15:
*(uint16_t *)(((uint8_t *)vram)+i*VIDEO (rowBytes) + j*2) = ((b&0xf8)>>3) | ((g&0xf8)<<2) | ((r&0xf8)<<7);
break;
}
}
}
}
void updateVRAM()
{
if (gui.redraw)
{
if (gui.devicelist.draw)
blend( gui.devicelist.pixmap, gui.backbuffer, gui.devicelist.pos );
if (gui.bootprompt.draw)
blend( gui.bootprompt.pixmap, gui.backbuffer, gui.bootprompt.pos );
if (gui.menu.draw)
blend( gui.menu.pixmap, gui.backbuffer, gui.menu.pos );
if (gui.infobox.draw)
blend( gui.infobox.pixmap, gui.backbuffer, gui.infobox.pos );
}
vramwrite ( gui.backbuffer->pixels, gui.backbuffer->width, gui.backbuffer->height );
if (gui.redraw)
{
memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
gui.redraw = false;
}
}
struct putc_info //Azi: exists on console.c & printf.c
{
char * str;
char * last_str;
};
static int
sputc(int c, struct putc_info * pi) //Azi: same as above
{
if (pi->last_str)
if (pi->str == pi->last_str) {
*(pi->str) = '\0';
return 0;
}
*(pi->str)++ = c;
return c;
}
int gprintf( window_t * window, const char * fmt, ...)
{
char *formattedtext;
va_list ap;
struct putc_info pi;
if ((formattedtext = malloc(1024)) != NULL) {
// format the text
va_start(ap, fmt);
pi.str = formattedtext;
pi.last_str = 0;
prf(fmt, ap, sputc, &pi);
*pi.str = '\0';
va_end(ap);
position_torigin, cursor, bounds;
int i;
int character;
origin.x = MAX( window->cursor.x, window->hborder );
origin.y = MAX( window->cursor.y, window->vborder );
bounds.x = ( window->width - window->hborder );
bounds.y = ( window->height - window->vborder );
cursor = origin;
font_t *font = &font_console;
for( i=0; i< strlen(formattedtext); i++ )
{
character = formattedtext[i];
character -= 32;
// newline ?
if( formattedtext[i] == '\n' )
{
cursor.x = window->hborder;
cursor.y += font->height;
if ( cursor.y > bounds.y )
cursor.y = origin.y;
continue;
}
// tab ?
if( formattedtext[i] == '\t' )
cursor.x += ( font->chars[0]->width * 5 );
// draw the character
if( font->chars[character])
blend(font->chars[character], window->pixmap, cursor);
cursor.x += font->chars[character]->width;
// check x pos and do newline
if ( cursor.x > bounds.x )
{
cursor.x = origin.x;
cursor.y += font->height;
}
// check y pos and reset to origin.y
if ( cursor.y > bounds.y )
cursor.y = origin.y;
}
// update cursor postition
window->cursor = cursor;
free(formattedtext);
return 0;
}
return 1;
}
int dprintf( window_t * window, const char * fmt, ...)
{
char *formattedtext;
va_list ap;
//window = &gui.debug;
struct putc_info pi;
if ((formattedtext = malloc(1024)) != NULL) {
// format the text
va_start(ap, fmt);
pi.str = formattedtext;
pi.last_str = 0;
prf(fmt, ap, sputc, &pi);
*pi.str = '\0';
va_end(ap);
position_torigin, cursor, bounds;
int i;
int character;
origin.x = MAX( gui.debug.cursor.x, window->hborder );
origin.y = MAX( gui.debug.cursor.y, window->vborder );
bounds.x = ( window->width - window->hborder );
bounds.y = ( window->height - window->vborder );
cursor = origin;
font_t *font = &font_console;
for( i=0; i< strlen(formattedtext); i++ )
{
character = formattedtext[i];
character -= 32;
// newline ?
if( formattedtext[i] == '\n' )
{
cursor.x = window->hborder;
cursor.y += font->height;
if ( cursor.y > bounds.y )
cursor.y = origin.y;
continue;
}
// tab ?
if( formattedtext[i] == '\t' )
cursor.x += ( font->chars[0]->width * 5 );
// draw the character
if( font->chars[character])
blend(font->chars[character], gui.backbuffer, cursor);
cursor.x += font->chars[character]->width;
// check x pos and do newline
if ( cursor.x > bounds.x )
{
cursor.x = origin.x;
cursor.y += font->height;
}
// check y pos and reset to origin.y
if ( cursor.y > bounds.y )
cursor.y = origin.y;
}
// update cursor postition
gui.debug.cursor = cursor;
free(formattedtext);
return 0;
}
return 1;
}
int vprf(const char * fmt, va_list ap)
{
int i;
int character;
char *formattedtext;
window_t *window = &gui.screen;
struct putc_info pi;
position_torigin, cursor, bounds;
font_t *font = &font_console;
if ((formattedtext = malloc(1024)) != NULL) {
// format the text
pi.str = formattedtext;
pi.last_str = 0;
prf(fmt, ap, sputc, &pi);
*pi.str = '\0';
origin.x = MAX( window->cursor.x, window->hborder );
origin.y = MAX( window->cursor.y, window->vborder );
bounds.x = ( window->width - ( window->hborder * 2 ) );
bounds.y = ( window->height - ( window->vborder * 2 ) );
cursor = origin;
for( i=0; i< strlen(formattedtext); i++ )
{
character = formattedtext[i];
character -= 32;
// newline ?
if( formattedtext[i] == '\n' )
{
cursor.x = window->hborder;
cursor.y += font->height;
if ( cursor.y > bounds.y )
{
gui.redraw = true;
updateVRAM();
cursor.y = window->vborder;
}
window->cursor.y = cursor.y;
continue;
}
// tab ?
if( formattedtext[i] == '\t' )
{
cursor.x = ( cursor.x / ( font->chars[0]->width * 8 ) + 1 ) * ( font->chars[0]->width * 8 );
continue;
}
cursor.x += font->chars[character]->width;
// check x pos and do newline
if ( cursor.x > bounds.x )
{
cursor.x = origin.x;
cursor.y += font->height;
}
// check y pos and reset to origin.y
if ( cursor.y > ( bounds.y + font->chars[0]->height) )
{
gui.redraw = true;
updateVRAM();
cursor.y = window->vborder;
}
// draw the character
if( font->chars[character])
blend(font->chars[character], gui.backbuffer, cursor);
}
// save cursor postition
window->cursor.x = cursor.x;
updateVRAM();
free(formattedtext);
return 0;
}
return 1;
}
void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p)
{
int i=0;
int y=0; // we need this to support multilines '\n'
int x=0;
for(i=0;i<strlen(ch);i++)
{
int cha=(int)ch[i];
cha-=32;
// newline ?
if( ch[i] == '\n' )
{
x = 0;
y += font->height;
continue;
}
// tab ?
if( ch[i] == '\t' )
x+=(font->chars[0]->width*5);
if(font->chars[cha])
blend(font->chars[cha], blendInto, pos(p.x+x, p.y+y));
x += font->chars[cha]->width;
}
}
void drawStrCenteredAt(char *text, font_t *font, pixmap_t *blendInto, position_t p)
{
int i = 0;
int width = 0;
// calculate the width in pixels
for(i=0;i<strlen(text);i++)
width += font->chars[text[i]-32]->width;
p.x = ( p.x - ( width / 2 ) );
p.y = ( p.y - ( font->height / 2 ) );
if ( p.x == -6 )
{
p.x = 0;
}
for(i=0;i<strlen(text);i++)
{
int cha=(int)text[i];
cha-=32;
if(font->chars[cha])
{
blend(font->chars[cha], blendInto, p);
p.x += font->chars[cha]->width;
}
}
}
int initFont(font_t *font, image_t *data)
{
unsigned int x = 0, y = 0, x2 = 0, x3 = 0;
int start = 0, end = 0, count = 0, space = 0;
bool monospaced = false;
font->height = data->image->height;
for( x = 0; x < data->image->width; x++)
{
start = end;
// if the pixel is red we've reached the end of the char
if( pixel( data->image, x, 0 ).value == 0xFFFF0000)
{
end = x + 1;
if( (font->chars[count] = malloc(sizeof(pixmap_t)) ) )
{
font->chars[count]->width = ( end - start) - 1;
font->chars[count]->height = font->height;
if ( ( font->chars[count]->pixels = malloc( font->chars[count]->width * data->image->height * 4) ) )
{
space += ( font->chars[count]->width * data->image->height * 4 );
// we skip the first line because there are just the red pixels for the char width
for( y = 1; y< (font->height); y++)
{
for( x2 = start, x3 = 0; x2 < end; x2++, x3++)
{
pixel( font->chars[count], x3, y ) = pixel( data->image, x2, y );
}
}
// check if font is monospaced
if( ( count > 0 ) && ( font->width != font->chars[count]->width ) )
monospaced = true;
font->width = font->chars[count]->width;
count++;
}
}
}
}
if(monospaced)
font->width = 0;
return 0;
}
void colorFont(font_t *font, uint32_t color)
{
if( !color )
return;
int x, y, width, height;
int count = 0;
pixel_t *buff;
while( font->chars[count++] )
{
width = font->chars[count-1]->width;
height = font->chars[count-1]->height;
for( y = 0; y < height; y++ )
{
for( x = 0; x < width; x++ )
{
buff = &(pixel( font->chars[count-1], x, y ));
if( buff->ch.a )
{
buff->ch.r = (color & 0xFFFF0000) >> 16;
buff->ch.g = (color & 0xFF00FF00) >> 8;
buff->ch.b = (color & 0xFF0000FF);
}
}
}
}
}
void makeRoundedCorners(pixmap_t *p)
{
int x,y;
int width=p->width-1;
int height=p->height-1;
// 10px rounded corner alpha values
uint8_t roundedCorner[10][10] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0xC0, 0xFF},
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0x00, 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0x00, 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0x00, 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0x40, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
};
uint8_t alpha=0;
for( y=0; y<10; y++)
{
for( x=0; x<10; x++)
{
// skip if the pixel should be visible
if(roundedCorner[y][x] != 0xFF)
{
alpha = ( roundedCorner[y][x] ? (uint8_t) (roundedCorner[y][x] * pixel(p, x, y).ch.a) / 255 : 0 );
// Upper left corner
pixel(p, x, y).ch.a = alpha;
// upper right corner
pixel(p, width-x,y).ch.a = alpha;
// lower left corner
pixel(p, x, height-y).ch.a = alpha;
// lower right corner
pixel(p, width-x, height-y).ch.a = alpha;
}
}
}
}
void showInfoBox(char *title, char *text)
{
int i, key, lines, visiblelines;
int currentline=0;
int cnt=0;
int offset=0;
if( !title || !text )
return;
position_t pos_title = pos ( gui.infobox.vborder, gui.infobox.vborder );
// calculate number of lines in the title
for ( i = 0, lines = 1; i<strlen(title); i++ )
if( title[i] == '\n')
lines++;
// y position of text is lines in title * height of font
position_t pos_text = pos( pos_title.x , pos_title.y + ( font_console.height * lines ));
// calculate number of lines in the text
for ( i=0, lines = 1; i<strlen(text); i++ )
if( text[i] == '\n')
lines++;
// if text ends with \n strip off
if( text[i] == '\n' || text[i] == '\0')
lines--;
visiblelines = ( ( gui.infobox.height - ( gui.infobox.vborder * 2 ) ) / font_console.height ) - 1;
// lets display the text and allow scroll thru using up down / arrows
while(1)
{
// move to current line in text
for( offset = 0, i = 0; offset < strlen(text); offset++ )
{
if( currentline == i)
break;
if( text[offset] =='\n')
i++;
}
// find last visible line in text and place \0
for( i = offset, cnt = 0; i < strlen(text); i++)
{
if(text[i]=='\n')
cnt++;
if ( cnt == visiblelines )
{
text[i]='\0';
break;
}
}
fillPixmapWithColor( gui.infobox.pixmap, gui.infobox.bgcolor);
makeRoundedCorners( gui.infobox.pixmap);
// print the title if present
if( title )
drawStr(title, &font_console, gui.infobox.pixmap, pos_title);
// print the text
drawStr( text + offset, &font_console, gui.infobox.pixmap, pos_text);
// restore \n in text
if ( cnt == visiblelines )
text[i] = '\n';
position_t pos_indicator = pos( gui.infobox.width - ( images[iTextScrollPrev].image->width - ( gui.infobox.vborder / 2) ), pos_text.y );
// draw prev indicator
if(offset)
{
blend( images[iTextScrollPrev].image, gui.infobox.pixmap, centeredAt( images[iTextScrollPrev].image, pos_indicator ));
}
// draw next indicator
if( lines > ( currentline + visiblelines ) )
{
pos_indicator.y = ( gui.infobox.height - ( ( images[iTextScrollNext].image->width + gui.infobox.vborder ) / 2 ) );
blend( images[iTextScrollNext].image, gui.infobox.pixmap, centeredAt( images[iTextScrollNext].image, pos_indicator ) );
}
gui.bootprompt.draw = false;
gui.infobox.draw = true;
gui.redraw = true;
updateVRAM();
key = getchar();
if( key == kUpArrowkey )
if( currentline > 0 )
currentline--;
if( key == kDownArrowkey )
if( lines > ( currentline + visiblelines ) )
currentline++;
if( key == kEscapeKey || key == 'q' || key == 'Q')
{
gui.infobox.draw = false;
gui.redraw = true;
updateVRAM();
break;
}
}
}
void animateProgressBar()
{
int y;
if( time18() > lasttime)
{
lasttime = time18();
pixmap_t *buffBar = images[iProgressBar].image;
uint32_t buff = buffBar->pixels[0].value;
memcpy( buffBar->pixels, buffBar->pixels + 1, ( (buffBar->width*buffBar->height) - 1 ) * 4 );
for( y = buffBar->height - 1; y > 0; y--)
pixel(buffBar, buffBar->width - 1, y) = pixel(buffBar, buffBar->width - 1, y - 1);
pixel(buffBar, buffBar->width-1, 0).value = buff;
}
}
void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress)
{
if(progress>100)
return;
p.x = ( p.x - ( width / 2 ) );
int todraw = (width * progress) / 100;
pixmap_t *buff = images[iProgressBar].image;
pixmap_t *buffBG = images[iProgressBarBackground].image;
if(!buff || !buffBG)
return;
pixmap_t progressbar;
progressbar.pixels=malloc(width * 4 * buff->height);
if(!progressbar.pixels)
return;
progressbar.width = width;
progressbar.height = buff->height;
int x=0,x2=0,y=0;
for(y=0; y<buff->height; y++)
{
for(x=0; x<todraw; x++, x2++)
{
if(x2 == (buff->width-1)) x2=0;
pixel(&progressbar, x,y).value = pixel(buff, x2,y).value;
}
x2=0;
}
for(y=0; y<buff->height; y++)
{
for(x=todraw, x2 = 0; x < width - 1; x++, x2++)
{
if(x2 == (buffBG->width -2 )) x2 = 0;
pixel(&progressbar, x,y).value = pixel(buffBG, x2,y).value;
}
if(progress < 100)
pixel(&progressbar, width - 1, y).value = pixel(buffBG, buffBG->width - 1, y).value;
if(progress == 0)
pixel(&progressbar, 0, y).value = pixel(buffBG, buffBG->width - 1, y).value;
x2=0;
}
blend(&progressbar, blendInto, p);
animateProgressBar();
free(progressbar.pixels);
}
void drawInfoMenuItems()
{
int i,n;
position_t position;
pixmap_t *selection = images[iMenuSelection].image;
pixmap_t *pbuff;
fillPixmapWithColor(gui.menu.pixmap, gui.menu.bgcolor);
makeRoundedCorners(gui.menu.pixmap);
uint8_t offset = infoMenuNativeBoot ? 0 : infoMenuItemsCount - 1;
position = pos(0,0);
for ( i = 0, n = iMenuBoot; i < infoMenuItemsCount; i++, n++)
{
if (i == infoMenuSelection)
blend(selection, gui.menu.pixmap, position);
pbuff = images[n].image;
if (offset && i >= INFOMENU_NATIVEBOOT_START && i <= INFOMENU_NATIVEBOOT_END)
blend( images[n + (iMenuHelp - iMenuBoot)].image , gui.menu.pixmap,
pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
else
blend( pbuff, gui.menu.pixmap,
pos((position.x + (gui.menu.hborder / 2)), position.y + ((selection->height - pbuff->height) / 2)));
drawStr(infoMenuItems[i].text, &font_console, gui.menu.pixmap,
pos(position.x + (pbuff->width + gui.menu.hborder),
position.y + ((selection->height - font_console.height) / 2)));
position.y += images[iMenuSelection].image->height;
}
gui.redraw = true;
}
int drawInfoMenu()
{
drawInfoMenuItems();
gui.menu.draw = true;
updateVRAM();
return 1;
}
int updateInfoMenu(int key)
{
switch (key)
{
case kUpArrowkey:// up arrow
if (infoMenuSelection > 0)
{
if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_END + 1)
infoMenuSelection -= 4;
else
infoMenuSelection--;
drawInfoMenuItems();
updateVRAM();
} else {
gui.menu.draw = false;
gui.redraw = true;
updateVRAM();
return CLOSE_INFO_MENU;
}
break;
case kDownArrowkey:// down arrow
if (infoMenuSelection < infoMenuItemsCount - 1)
{
if(!infoMenuNativeBoot && infoMenuSelection == INFOMENU_NATIVEBOOT_START - 1)
infoMenuSelection += 4;
else
infoMenuSelection++;
drawInfoMenuItems();
updateVRAM();
}
break;
case kReturnKey:
key = 0;
if( infoMenuSelection == MENU_SHOW_MEMORY_INFO )
showInfoBox( "Memory Info. Press q to quit.\n", getMemoryInfoString());
else if( infoMenuSelection == MENU_SHOW_VIDEO_INFO )
showInfoBox( getVBEInfoString(), getVBEModeInfoString() );
else if( infoMenuSelection == MENU_SHOW_HELP )
showHelp();
else
{
int buff = infoMenuSelection;
infoMenuSelection = 0;
return buff;
}
break;
}
return DO_NOT_BOOT;
}
uint16_t bootImageWidth = 0;
uint16_t bootImageHeight = 0;
uint8_t *bootImageData = NULL;
static bool usePngImage = true;
//==========================================================================
// loadBootGraphics
static void loadBootGraphics(void)
{
if (bootImageData != NULL) {
return;
}
char dirspec[256];
if ((strlen(theme_name) + 24) > sizeof(dirspec)) {
usePngImage = false;
return;
}
sprintf(dirspec, "/Extra/Themes/%s/boot.png", theme_name);
if (loadPngImage(dirspec, &bootImageWidth, &bootImageHeight, &bootImageData) != 0) {
#ifdef CONFIG_EMBED_THEME
if ((loadEmbeddedPngImage(__boot_png, __boot_png_len, &bootImageWidth, &bootImageHeight, &bootImageData)) != 0)
#endif
usePngImage = false;
}
}
//==========================================================================
// drawBootGraphics
void drawBootGraphics(void)
{
int pos;
int length;
const char *dummyVal;
int oldScreenWidth, oldScreenHeight;
bool legacy_logo;
uint16_t x, y;
if (getBoolForKey("Legacy Logo", &legacy_logo, &bootInfo->bootConfig) && legacy_logo) {
usePngImage = false;
} else if (bootImageData == NULL) {
loadBootGraphics();
}
// parse screen size parameters
if (getIntForKey("boot_width", &pos, &bootInfo->themeConfig) && pos > 0) {
screen_params[0] = pos;
} else {
screen_params[0] = DEFAULT_SCREEN_WIDTH;
}
if (getIntForKey("boot_height", &pos, &bootInfo->themeConfig) && pos > 0) {
screen_params[1] = pos;
} else {
screen_params[1] = DEFAULT_SCREEN_HEIGHT;
}
// Save current screen resolution.
oldScreenWidth = gui.screen.width;
oldScreenHeight = gui.screen.height;
gui.screen.width = screen_params[0];
gui.screen.height = screen_params[1];
// find best matching vesa mode for our requested width & height
getGraphicModeParams(screen_params);
// Set graphics mode if the booter was in text mode or the screen resolution has changed.
if (bootArgs->Video.v_display == VGA_TEXT_MODE
|| (screen_params[0] != oldScreenWidth && screen_params[1] != oldScreenHeight) )
{
setVideoMode(GRAPHICS_MODE, 0);
}
if (getValueForKey("-checkers", &dummyVal, &length, &bootInfo->bootConfig)) {
drawCheckerBoard();
} else {
// Fill the background to 75% grey (same as BootX).
drawColorRectangle(0, 0, screen_params[0], screen_params[1], 0x01);
}
if ((bootImageData) && (usePngImage)) {
x = (screen_params[0] - MIN(bootImageWidth, screen_params[0])) / 2;
y = (screen_params[1] - MIN(bootImageHeight, screen_params[1])) / 2;
// Draw the image in the center of the display.
blendImage(x, y, bootImageWidth, bootImageHeight, bootImageData);
} else {
uint8_t *appleBootPict;
bootImageData = NULL;
bootImageWidth = kAppleBootWidth;
bootImageHeight = kAppleBootHeight;
// Prepare the data for the default Apple boot image.
appleBootPict = (uint8_t *) decodeRLE(gAppleBootPictRLE, kAppleBootRLEBlocks, bootImageWidth * bootImageHeight);
if (appleBootPict) {
convertImage(bootImageWidth, bootImageHeight, appleBootPict, &bootImageData);
if (bootImageData) {
x = (screen_params[0] - MIN(kAppleBootWidth, screen_params[0])) / 2;
y = (screen_params[1] - MIN(kAppleBootHeight, screen_params[1])) / 2;
drawDataRectangle(x, y, kAppleBootWidth, kAppleBootHeight, bootImageData);
free(bootImageData);
}
free(appleBootPict);
}
}
}
branches/rewrite/i386/boot2/appleClut8.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
* Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 2.0 (the "License"). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef __BOOT2_APPLECLUT8_H
#define __BOOT2_APPLECLUT8_H
static const unsigned char appleClut8[ 256 * 3 ] =
{
0xff,0xff,0xff, 0xbf,0xbf,0xbf, 0xbe,0xbe,0xbe, 0xbd,0xbd,0xbd,
0xbc,0xbc,0xbc, 0xff,0xff,0x00, 0xba,0xba,0xba, 0xb9,0xb9,0xb9,
0xb8,0xb8,0xb8, 0xb7,0xb7,0xb7, 0xb6,0xb6,0xb6, 0xb5,0xb5,0xb5,
0xb4,0xb4,0xb4, 0xb3,0xb3,0xb3, 0xb2,0xb2,0xb2, 0x00,0x00,0x00,
0xb1,0xb1,0xb1, 0xb0,0xb0,0xb0, 0xaf,0xaf,0xaf, 0xae,0xae,0xae,
0xad,0xad,0xad, 0xac,0xac,0xac, 0xab,0xab,0xab, 0xaa,0xaa,0xaa,
0xff,0x00,0xff, 0xa9,0xa9,0xa9, 0xa8,0xa8,0xa8, 0xa7,0xa7,0xa7,
0xa6,0xa6,0xa6, 0xa5,0xa5,0xa5, 0xa4,0xa4,0xa4, 0xa3,0xa3,0xa3,
0xa2,0xa2,0xa2, 0xa1,0xa1,0xa1, 0xa0,0xa0,0xa0, 0xff,0x00,0x00,
0x9f,0x9f,0x9f, 0x9e,0x9e,0x9e, 0x9d,0x9d,0x9d, 0x9c,0x9c,0x9c,
0x9b,0x9b,0x9b, 0x9a,0x9a,0x9a, 0xcc,0xcc,0xff, 0xcc,0xcc,0xcc,
0x99,0x99,0x99, 0x98,0x98,0x98, 0x97,0x97,0x97, 0x96,0x96,0x96,
0x95,0x95,0x95, 0x94,0x94,0x94, 0x93,0x93,0x93, 0x92,0x92,0x92,
0x91,0x91,0x91, 0x90,0x90,0x90, 0x8f,0x8f,0x8f, 0x8e,0x8e,0x8e,
0x8d,0x8d,0x8d, 0x8c,0x8c,0x8c, 0x8b,0x8b,0x8b, 0x8a,0x8a,0x8a,
0x89,0x89,0x89, 0x87,0x87,0x87, 0x86,0x86,0x86, 0x85,0x85,0x85,
0x84,0x84,0x84, 0x83,0x83,0x83, 0x82,0x82,0x82, 0x81,0x81,0x81,
0x80,0x80,0x80, 0x7f,0x7f,0x7f, 0x7e,0x7e,0x7e, 0x7d,0x7d,0x7d,
0x7c,0x7c,0x7c, 0x7b,0x7b,0x7b, 0x7a,0x7a,0x7a, 0x79,0x79,0x79,
0x78,0x78,0x78, 0x76,0x76,0x76, 0x75,0x75,0x75, 0x74,0x74,0x74,
0x73,0x73,0x73, 0x72,0x72,0x72, 0x71,0x71,0x71, 0x70,0x70,0x70,
0x6f,0x6f,0x6f, 0x6e,0x6e,0x6e, 0x6d,0x6d,0x6d, 0x6c,0x6c,0x6c,
0x6b,0x6b,0x6b, 0x6a,0x6a,0x6a, 0x69,0x69,0x69, 0x68,0x68,0x68,
0x67,0x67,0x67, 0x66,0x66,0x66, 0x64,0x64,0x64, 0x63,0x63,0x63,
0x62,0x62,0x62, 0x61,0x61,0x61, 0x60,0x60,0x60, 0x5f,0x5f,0x5f,
0x5e,0x5e,0x5e, 0x5d,0x5d,0x5d, 0x5c,0x5c,0x5c, 0x5b,0x5b,0x5b,
0x5a,0x5a,0x5a, 0x59,0x59,0x59, 0x58,0x58,0x58, 0x57,0x57,0x57,
0x56,0x56,0x56, 0x54,0x54,0x54, 0x53,0x53,0x53, 0x52,0x52,0x52,
0x51,0x51,0x51, 0x50,0x50,0x50, 0x4f,0x4f,0x4f, 0x4e,0x4e,0x4e,
0x4d,0x4d,0x4d, 0x4c,0x4c,0x4c, 0x4b,0x4b,0x4b, 0x4a,0x4a,0x4a,
0x49,0x49,0x49, 0x48,0x48,0x48, 0x47,0x47,0x47, 0x46,0x46,0x46,
0x45,0x45,0x45, 0x43,0x43,0x43, 0x42,0x42,0x42, 0x41,0x41,0x41,
0x40,0x40,0x40, 0x3f,0x3f,0x3f, 0x3e,0x3e,0x3e, 0x3d,0x3d,0x3d,
0x3c,0x3c,0x3c, 0x3b,0x3b,0x3b, 0x3a,0x3a,0x3a, 0x39,0x39,0x39,
0x38,0x38,0x38, 0x37,0x37,0x37, 0x36,0x36,0x36, 0x35,0x35,0x35,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x00,0xff,0xff, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x00,0xff,0x00, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x00,0x00,0xff, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0xdd,0x00,0x00, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x00,0xbb,0x00,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65,
0x65,0x65,0x65, 0x65,0x65,0x65, 0x65,0x65,0x65, 0xbb,0xbb,0xbb,
0x65,0x65,0x65, 0x88,0x88,0x88, 0x77,0x77,0x77, 0x55,0x55,0x55,
0x44,0x44,0x44, 0x22,0x22,0x22, 0x65,0x65,0x65, 0x00,0x00,0x00
};
#endif /* !__BOOT2_APPLECLUT8_H */
branches/rewrite/i386/boot2/IOHibernatePrivate.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
/*
* Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef KERNEL
#include <crypto/aes.h>
#endif
struct IOPolledFileExtent
{
uint64_tstart;
uint64_tlength;
};
typedef struct IOPolledFileExtent IOPolledFileExtent;
struct IOHibernateImageHeader
{
uint64_timageSize;
uint64_timage1Size;
uint32_trestore1CodePage;
uint32_trestore1PageCount;
uint32_trestore1CodeOffset;
uint32_trestore1StackOffset;
uint32_tpageCount;
uint32_tbitmapSize;
uint32_trestore1Sum;
uint32_timage1Sum;
uint32_timage2Sum;
uint32_tactualRestore1Sum;
uint32_tactualImage1Sum;
uint32_tactualImage2Sum;
uint32_tactualUncompressedPages;
uint32_tconflictCount;
uint32_tnextFree;
uint32_tsignature;
uint32_tprocessorFlags;
uint32_t runtimePages;
uint32_t runtimePageCount;
uint8_treserved2[16];
uint64_tencryptStart;
uint64_tmachineSignature;
uint32_t previewSize;
uint32_t previewPageListSize;
uint32_tdiag[4];
int32_tgraphicsInfoOffset;
int32_tcryptVarsOffset;
int32_tmemoryMapOffset;
uint32_t memoryMapSize;
uint32_t systemTableOffset;
uint32_treserved[77];// make sizeof == 512
uint32_tfileExtentMapSize;
IOPolledFileExtentfileExtentMap[2];
};
typedef struct IOHibernateImageHeader IOHibernateImageHeader;
struct hibernate_bitmap_t
{
uint32_tfirst_page;
uint32_tlast_page;
uint32_tbitmapwords;
uint32_tbitmap[0];
};
typedef struct hibernate_bitmap_t hibernate_bitmap_t;
struct hibernate_page_list_t
{
uint32_t list_size;
uint32_t page_count;
uint32_t bank_count;
hibernate_bitmap_t bank_bitmap[0];
};
typedef struct hibernate_page_list_t hibernate_page_list_t;
#if defined(_AES_H)
struct hibernate_cryptwakevars_t
{
uint8_t aes_iv[AES_BLOCK_SIZE];
};
typedef struct hibernate_cryptwakevars_t hibernate_cryptwakevars_t;
struct hibernate_cryptvars_t
{
uint8_t aes_iv[AES_BLOCK_SIZE];
aes_ctx ctx;
};
typedef struct hibernate_cryptvars_t hibernate_cryptvars_t;
#endif /* defined(_AES_H) */
enum
{
kIOHibernateProgressCount = 19,
kIOHibernateProgressWidth = 7,
kIOHibernateProgressHeight = 16,
kIOHibernateProgressSpacing = 3,
kIOHibernateProgressOriginY = 81,
kIOHibernateProgressSaveUnderSize = 2*5+14*2,
kIOHibernateProgressLightGray = 230,
kIOHibernateProgressMidGray = 174,
kIOHibernateProgressDarkGray = 92
};
enum
{
kIOHibernatePostWriteSleep = 0,
kIOHibernatePostWriteWake = 1,
kIOHibernatePostWriteHalt = 2,
kIOHibernatePostWriteRestart = 3
};
struct hibernate_graphics_t
{
uint32_t physicalAddress;// Base address of video memory
uint32_t mode;//
uint32_t rowBytes; // Number of bytes per pixel row
uint32_t width; // Width
uint32_t height; // Height
uint32_t depth; // Pixel Depth
uint8_t progressSaveUnder[kIOHibernateProgressCount][kIOHibernateProgressSaveUnderSize];
};
typedef struct hibernate_graphics_t hibernate_graphics_t;
#define DECLARE_IOHIBERNATEPROGRESSALPHA\
static const uint8_t gIOHibernateProgressAlpha\
[kIOHibernateProgressHeight][kIOHibernateProgressWidth] = \
{\
{ 0x00,0x63,0xd8,0xf0,0xd8,0x63,0x00 },\
{ 0x51,0xff,0xff,0xff,0xff,0xff,0x51 },\
{ 0xae,0xff,0xff,0xff,0xff,0xff,0xae },\
{ 0xc3,0xff,0xff,0xff,0xff,0xff,0xc3 },\
{ 0xc3,0xff,0xff,0xff,0xff,0xff,0xc3 },\
{ 0xc3,0xff,0xff,0xff,0xff,0xff,0xc3 },\
{ 0xc3,0xff,0xff,0xff,0xff,0xff,0xc3 },\
{ 0xc3,0xff,0xff,0xff,0xff,0xff,0xc3 },\
{ 0xc3,0xff,0xff,0xff,0xff,0xff,0xc3 },\
{ 0xc3,0xff,0xff,0xff,0xff,0xff,0xc3 },\
{ 0xc3,0xff,0xff,0xff,0xff,0xff,0xc3 },\
{ 0xc3,0xff,0xff,0xff,0xff,0xff,0xc3 },\
{ 0xc3,0xff,0xff,0xff,0xff,0xff,0xc3 },\
{ 0xae,0xff,0xff,0xff,0xff,0xff,0xae },\
{ 0x54,0xff,0xff,0xff,0xff,0xff,0x54 },\
{ 0x00,0x66,0xdb,0xf3,0xdb,0x66,0x00 }\
};
#ifdef KERNEL
#ifdef __cplusplus
void IOHibernateSystemInit(IOPMrootDomain * rootDomain);
IOReturn IOHibernateSystemSleep(void);
IOReturn IOHibernateSystemHasSlept(void);
IOReturn IOHibernateSystemWake(void);
IOReturn IOHibernateSystemPostWake(void);
#endif /* __cplusplus */
#ifdef _SYS_CONF_H_
typedef void (*kern_get_file_extents_callback_t)(void * ref, uint64_t start, uint64_t size);
struct kern_direct_file_io_ref_t *
kern_open_file_for_direct_io(const char * name,
kern_get_file_extents_callback_t callback,
void * callback_ref,
dev_t * device,
uint64_t * partitionbase_result,
uint64_t * maxiocount_result);
void
kern_close_file_for_direct_io(struct kern_direct_file_io_ref_t * ref);
int
kern_write_file(struct kern_direct_file_io_ref_t * ref, off_t offset, caddr_t addr, vm_size_t len);
int get_kernel_symfile(struct proc *p, char const **symfile);
#endif /* _SYS_CONF_H_ */
hibernate_page_list_t *
hibernate_page_list_allocate(void);
kern_return_t
hibernate_setup(IOHibernateImageHeader * header,
uint32_t free_page_ratio,
uint32_t free_page_time,
hibernate_page_list_t ** page_list_ret,
hibernate_page_list_t ** page_list_wired_ret,
boolean_t * encryptedswap);
kern_return_t
hibernate_teardown(hibernate_page_list_t * page_list,
hibernate_page_list_t * page_list_wired);
kern_return_t
hibernate_processor_setup(IOHibernateImageHeader * header);
void
hibernate_vm_lock(void);
void
hibernate_vm_unlock(void);
// mark pages not to be saved, based on VM system accounting
void
hibernate_page_list_setall(hibernate_page_list_t * page_list,
hibernate_page_list_t * page_list_wired,
uint32_t * pagesOut);
// mark pages to be saved, or pages not to be saved but available
// for scratch usage during restore
void
hibernate_page_list_setall_machine(hibernate_page_list_t * page_list,
hibernate_page_list_t * page_list_wired,
uint32_t * pagesOut);
// mark pages not to be saved and not for scratch usage during restore
void
hibernate_page_list_set_volatile( hibernate_page_list_t * page_list,
hibernate_page_list_t * page_list_wired,
uint32_t * pagesOut);
void
hibernate_page_list_discard(hibernate_page_list_t * page_list);
void
hibernate_set_page_state(hibernate_page_list_t * page_list, hibernate_page_list_t * page_list_wired,
vm_offset_t ppnum, vm_offset_t count, uint32_t kind);
void
hibernate_page_bitset(hibernate_page_list_t * list, boolean_t set, uint32_t page);
boolean_t
hibernate_page_bittst(hibernate_page_list_t * list, uint32_t page);
hibernate_bitmap_t *
hibernate_page_bitmap_pin(hibernate_page_list_t * list, uint32_t * page);
uint32_t
hibernate_page_bitmap_count(hibernate_bitmap_t * bitmap, uint32_t set, uint32_t page);
void
hibernate_restore_phys_page(uint64_t src, uint64_t dst, uint32_t len, uint32_t procFlags);
void
hibernate_machine_init(void);
uint32_t
hibernate_write_image(void);
long
hibernate_machine_entrypoint(IOHibernateImageHeader * header, void * p2, void * p3, void * p4);
long
hibernate_kernel_entrypoint(IOHibernateImageHeader * header, void * p2, void * p3, void * p4);
void
hibernate_newruntime_map(void * map, vm_size_t map_size,
uint32_t system_table_offset);
extern uint32_t gIOHibernateState;
extern uint32_t gIOHibernateMode;
extern uint32_t gIOHibernateFreeTime;// max time to spend freeing pages (ms)
extern uint8_t gIOHibernateRestoreStack[];
extern uint8_t gIOHibernateRestoreStackEnd[];
extern IOHibernateImageHeader * gIOHibernateCurrentHeader;
extern hibernate_graphics_t * gIOHibernateGraphicsInfo;
extern hibernate_cryptwakevars_t * gIOHibernateCryptWakeVars;
#define HIBLOG(fmt, args...)\
{ kprintf(fmt, ## args); printf(fmt, ## args); }
#define HIBPRINT(fmt, args...)\
{ kprintf(fmt, ## args); }
#endif /* KERNEL */
// gIOHibernateState, kIOHibernateStateKey
enum
{
kIOHibernateStateInactive = 0,
kIOHibernateStateHibernating = 1,/* writing image */
kIOHibernateStateWakingFromHibernate = 2/* booted and restored image */
};
// gIOHibernateMode, kIOHibernateModeKey
enum
{
kIOHibernateModeOn = 0x00000001,
kIOHibernateModeSleep = 0x00000002,
kIOHibernateModeEncrypt = 0x00000004,
kIOHibernateModeDiscardCleanInactive = 0x00000008,
kIOHibernateModeDiscardCleanActive = 0x00000010,
kIOHibernateModeSwitch= 0x00000020,
kIOHibernateModeRestart= 0x00000040
};
// IOHibernateImageHeader.signature
enum
{
kIOHibernateHeaderSignature = 0x73696d65,
kIOHibernateHeaderInvalidSignature = 0x7a7a7a7a
};
// kind for hibernate_set_page_state()
enum
{
kIOHibernatePageStateFree = 0,
kIOHibernatePageStateWiredSave = 1,
kIOHibernatePageStateUnwiredSave = 2
};
#define kIOHibernateModeKey"Hibernate Mode"
#define kIOHibernateFileKey"Hibernate File"
#define kIOHibernateFreeRatioKey"Hibernate Free Ratio"
#define kIOHibernateFreeTimeKey"Hibernate Free Time"
#define kIOHibernateStateKey"IOHibernateState"
#define kIOHibernateFeatureKey"Hibernation"
#define kIOHibernatePreviewBufferKey"IOPreviewBuffer"
#define kIOHibernatePreviewActiveKey"IOHibernatePreviewActive"
// values for kIOHibernatePreviewActiveKey
enum {
kIOHibernatePreviewActive = 0x00000001,
kIOHibernatePreviewUpdates = 0x00000002
};
#define kIOHibernateBootImageKey"boot-image"
#define kIOHibernateBootImageKeyKey"boot-image-key"
#define kIOHibernateBootSignatureKey"boot-signature"
#define kIOHibernateMemorySignatureKey "memory-signature"
#define kIOHibernateMemorySignatureEnvKey "mem-sig"
#define kIOHibernateMachineSignatureKey "machine-signature"
#define kIOHibernateRTCVariablesKey"IOHibernateRTCVariables"
#define kIOHibernateBootSwitchVarsKey"boot-switch-vars"
#ifdef __cplusplus
}
#endif
branches/rewrite/i386/boot2/gui.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
/*
* gui.h
*
*
* Created by Jasmin Fazlic on 18.12.08.
* Copyright 2008/09 Jasmin Fazlic All rights reserved.
* Copyright 2008/09 iNDi All rights reserved.
*
*/
#ifndef __BOOT2_GUI_H
#define __BOOT2_GUI_H
#include "boot.h"
#include "bootstruct.h"
#include "graphics.h"
#include "graphic_utils.h"
#include "picopng.h"
#define CHARACTERS_COUNT223
#define BOOT_NORMAL0
#define BOOT_VERBOSE1
#define BOOT_IGNORECACHE2
#define BOOT_SINGLEUSER3
#define DO_NOT_BOOT4
#define CLOSE_INFO_MENU5
#define INFOMENU_NATIVEBOOT_START1
#define INFOMENU_NATIVEBOOT_END3
#define MENU_SHOW_MEMORY_INFO4
#define MENU_SHOW_VIDEO_INFO5
#define MENU_SHOW_HELP6
enum {
HorizontalLayout= 0,
VerticalLayout= 1
};
enum {
kBackspaceKey= 0x08,
kTabKey= 0x09,
kReturnKey= '\r',
kEscapeKey= 0x1b,
kUpArrowkey= 0x4800,
kDownArrowkey= 0x5000,
kASCIIKeyMask= 0x7f,
kF5Key= 0x3f00,
kF10Key= 0x4400
};
/*
* Menu item structure.
*/
typedef struct {
position_tpos;
char*text;
boolenabled;
boolexpandable;
} menuitem_t;
/*
* Image structure.
*/
typedef struct {
pixmap_t*image;
charname[32];
} image_t;
/*
* Font structure.
*/
typedef struct {
uint16_theight;// Font Height
uint16_twidth;// Font Width for monospace font only
pixmap_t*chars[CHARACTERS_COUNT];
} font_t;
/*
* Window structure.
*/
typedef struct
{
position_tpos;// X,Y Position of window on screen
pixmap_t*pixmap;// Buffer
uint16_twidth;// Width
uint16_theight;// Height
uint16_thborder;// Horizontal border
uint16_tvborder;// Vertical border
uint16_ticonspacing;// Icon spacing
position_tcursor;// Text Cursor X,Y Position will be multiples of font width & height
uint32_tbgcolor;// Background color AARRGGBB
uint32_tfgcolor;// Foreground color AARRGGBB
uint32_tfont_small_color;// Color for small font AARRGGBB
uint32_tfont_console_color;// Color for consle font AARRGGBB
booldraw;// Draw flag
} window_t;
/*
* gui structure
*/
typedef struct
{
uint8_tmaxdevices;//
uint8_tlayout;// Horizontal or Vertical layout
pixmap_t*backbuffer;// Off screen buffer
window_tscreen;//
window_tbackground;// Position of background graphic within screen
window_tlogo;// Logo
window_tbootprompt;// Bootprompt Window
window_tdevicelist;// Devicelist Window
window_tinfobox;// Infobox Window
window_tmenu;// Menu
window_tprogressbar;// Progress bar
window_tcountdown;// Countdown text
window_tdebug;// Debug
boolinitialised;// Initialised
boolredraw;// Redraw flag
} gui_t;
gui_t gui;// gui structure
font_t font_small;
font_t font_console;
int initGUI();
void drawBackground();
void setupDeviceList(config_file_t *theme);
void drawDeviceIcon(BVRef device, pixmap_t *buffer, position_t p, bool isSelected);
void drawDeviceList(int start, int end, int selection);
void drawProgressBar(pixmap_t *blendInto, uint16_t width, position_t p, uint8_t progress);
void showInfoBox(char *title, char *text);
int dprintf( window_t * window, const char * fmt, ...);
int gprintf( window_t * window, const char * fmt, ...);
int vprf(const char * fmt, va_list ap);
int drawInfoMenu();
int updateInfoMenu(int key);
void drawInfoMenuItems();
void showGraphicBootPrompt();
void clearGraphicBootPrompt();
void updateGraphicBootPrompt();
void updateVRAM();
void drawStr(char *ch, font_t *font, pixmap_t *blendInto, position_t p);
void drawStrCenteredAt(char *ch, font_t *font, pixmap_t *blendInto, position_t p);
#endif /* !__BOOT2_GUI_H */
branches/rewrite/i386/boot2/appleboot.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
/*
* Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 2.0 (the "License"). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* appleboot.h - Apple logo shown durring boot
*
* Copyright (c) 2002 Apple Computer, Inc.
*
* DRI: Josh de Cesare
*/
#define kAppleBootWidth(128)
#define kAppleBootHeight(128)
#define kAppleBootOffset(0)
#define kAppleBootFrames(1)
#define kAppleBootFPS(0)
#define kAppleBootRLEBlocks (686)
// The original data was 16K in size (128x128) and would make the booter
// cross a 64K segment boundary. boot0 cannot load more than 127 sectors
// without changes. To eiminate that complexity, the data was run length
// encoded to save space. The reduced size is 1372 bytes.
const unsigned char gAppleBootPictRLE[] =
{
0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0x50, 0x01, 0x01, 0x02, 0x01, 0x17,
0x01, 0x34, 0x01, 0x47, 0x03, 0x50, 0x01, 0x13, 0x76, 0x01, 0x01, 0x03,
0x01, 0x20, 0x01, 0x40, 0x06, 0x50, 0x01, 0x13, 0x75, 0x01, 0x01, 0x1a,
0x01, 0x42, 0x07, 0x50, 0x01, 0xfa, 0x01, 0x0a, 0x73, 0x01, 0x01, 0x07,
0x01, 0x34, 0x09, 0x50, 0x01, 0x43, 0x01, 0x02, 0x72, 0x01, 0x01, 0x0e,
0x01, 0x43, 0x0a, 0x50, 0x01, 0x36, 0x72, 0x01, 0x01, 0x14, 0x01, 0x4a,
0x0b, 0x50, 0x01, 0x20, 0x71, 0x01, 0x01, 0x12, 0x01, 0x4b, 0x0b, 0x50,
0x01, 0x4d, 0x01, 0x0b, 0x70, 0x01, 0x01, 0x0b, 0x01, 0x48, 0x0c, 0x50,
0x01, 0xf9, 0x70, 0x01, 0x01, 0x03, 0x01, 0x3e, 0x0d, 0x50, 0x01, 0x1f,
0x70, 0x01, 0x01, 0x2f, 0x0d, 0x50, 0x01, 0x48, 0x01, 0x06, 0x6f, 0x01,
0x01, 0x15, 0x01, 0x4f, 0x0d, 0x50, 0x01, 0x27, 0x6f, 0x01, 0x01, 0x02,
0x01, 0x3f, 0x0d, 0x50, 0x01, 0x45, 0x01, 0xf7, 0x6f, 0x01, 0x01, 0x1d,
0x0e, 0x50, 0x01, 0x19, 0x6f, 0x01, 0x01, 0x02, 0x01, 0x40, 0x0d, 0x50,
0x01, 0x2f, 0x70, 0x01, 0x01, 0x15, 0x0d, 0x50, 0x01, 0x3b, 0x01, 0x03,
0x70, 0x01, 0x01, 0x34, 0x0c, 0x50, 0x01, 0x3f, 0x01, 0x07, 0x70, 0x01,
0x01, 0xf7, 0x01, 0x47, 0x0b, 0x50, 0x01, 0xf9, 0x01, 0x07, 0x71, 0x01,
0x01, 0x14, 0x0b, 0x50, 0x01, 0x36, 0x01, 0xf7, 0x72, 0x01, 0x01, 0x24,
0x09, 0x50, 0x01, 0x4d, 0x01, 0x28, 0x74, 0x01, 0x01, 0x33, 0x08, 0x50,
0x01, 0x3f, 0x01, 0x14, 0x75, 0x01, 0x01, 0x3a, 0x06, 0x50, 0x01, 0x41,
0x01, 0x1f, 0x01, 0x02, 0x76, 0x01, 0x01, 0x3a, 0x03, 0x50, 0x01, 0x48,
0x01, 0x35, 0x01, 0x17, 0x01, 0x02, 0x78, 0x01, 0x01, 0x15, 0x01, 0x33,
0x01, 0x27, 0x01, 0x15, 0x01, 0xf7, 0x67, 0x01, 0x01, 0x02, 0x01, 0x08,
0x01, 0x0e, 0x01, 0x13, 0x01, 0x14, 0x01, 0x12, 0x01, 0x0d, 0x01, 0x06,
0x01, 0x02, 0x1c, 0x01, 0x01, 0x04, 0x01, 0x0b, 0x01, 0x12, 0x01, 0x17,
0x01, 0x19, 0x01, 0x15, 0x01, 0x11, 0x01, 0x08, 0x01, 0x02, 0x4e, 0x01,
0x01, 0x02, 0x01, 0x11, 0x01, 0x26, 0x01, 0x39, 0x01, 0x44, 0x01, 0x4c,
0x01, 0x4f, 0x02, 0x50, 0x01, 0x4f, 0x01, 0x4d, 0x01, 0x4a, 0x01, 0x3f,
0x01, 0x31, 0x01, 0x19, 0x01, 0xf7, 0x15, 0x01, 0x01, 0x0b, 0x01, 0x1c,
0x01, 0x2e, 0x01, 0xf9, 0x01, 0x46, 0x01, 0x4d, 0x04, 0x50, 0x01, 0x4f,
0x01, 0x4b, 0x01, 0x42, 0x01, 0x34, 0x01, 0x1f, 0x01, 0x0a, 0x49, 0x01,
0x01, 0xf7, 0x01, 0x21, 0x01, 0x3f, 0x01, 0x4f, 0x0d, 0x50, 0x01, 0x47,
0x01, 0x2d, 0x01, 0x0d, 0x10, 0x01, 0x01, 0x0d, 0x01, 0x25, 0x01, 0x3d,
0x01, 0xfa, 0x0e, 0x50, 0x01, 0x4c, 0x01, 0x37, 0x01, 0x15, 0x45, 0x01,
0x01, 0x04, 0x01, 0x25, 0x01, 0x45, 0x12, 0x50, 0x01, 0x4d, 0x01, 0x39,
0x01, 0x19, 0x01, 0x02, 0x0a, 0x01, 0x01, 0x09, 0x01, 0x21, 0x01, 0xf9,
0x01, 0x4d, 0x14, 0x50, 0x01, 0xf9, 0x01, 0x15, 0x42, 0x01, 0x01, 0x17,
0x01, 0x42, 0x17, 0x50, 0x01, 0x42, 0x01, 0x27, 0x01, 0x0e, 0x01, 0x02,
0x03, 0x01, 0x01, 0x02, 0x01, 0x0b, 0x01, 0x1f, 0x01, 0x38, 0x01, 0x4b,
0x19, 0x50, 0x01, 0x33, 0x01, 0x06, 0x3e, 0x01, 0x01, 0x03, 0x01, 0x2e,
0x1b, 0x50, 0x01, 0x4d, 0x01, 0x43, 0x01, 0x3a, 0x01, 0x37, 0x01, 0x3a,
0x01, 0x42, 0x01, 0x4d, 0x1d, 0x50, 0x01, 0x42, 0x01, 0x0e, 0x3c, 0x01,
0x01, 0x0a, 0x01, 0xf9, 0x41, 0x50, 0x01, 0x48, 0x01, 0x13, 0x3a, 0x01,
0x01, 0x0d, 0x01, 0x45, 0x43, 0x50, 0x01, 0x4b, 0x01, 0x12, 0x38, 0x01,
0x01, 0x10, 0x01, 0x48, 0x45, 0x50, 0x01, 0x48, 0x01, 0x0b, 0x36, 0x01,
0x01, 0x0c, 0x01, 0x48, 0x47, 0x50, 0x01, 0x3d, 0x01, 0x03, 0x34, 0x01,
0x01, 0x07, 0x01, 0x42, 0x49, 0x50, 0x01, 0x21, 0x34, 0x01, 0x01, 0x37,
0x49, 0x50, 0x01, 0x42, 0x01, 0x12, 0x33, 0x01, 0x01, 0x22, 0x49, 0x50,
0x01, 0x34, 0x01, 0xf7, 0x33, 0x01, 0x01, 0x0b, 0x01, 0x4b, 0x48, 0x50,
0x01, 0x2c, 0x35, 0x01, 0x01, 0x36, 0x48, 0x50, 0x01, 0x29, 0x35, 0x01,
0x01, 0x11, 0x01, 0x4f, 0x47, 0x50, 0x01, 0x2e, 0x36, 0x01, 0x01, 0x36,
0x47, 0x50, 0x01, 0x3a, 0x01, 0x02, 0x35, 0x01, 0x01, 0x0b, 0x01, 0xfa,
0x46, 0x50, 0x01, 0x46, 0x01, 0x08, 0x36, 0x01, 0x01, 0x26, 0x46, 0x50,
0x01, 0x4e, 0x01, 0x15, 0x36, 0x01, 0x01, 0x02, 0x01, 0x40, 0x46, 0x50,
0x01, 0x31, 0x37, 0x01, 0x01, 0x0e, 0x01, 0x4e, 0x45, 0x50, 0x01, 0x49,
0x01, 0x08, 0x37, 0x01, 0x01, 0x25, 0x46, 0x50, 0x01, 0x29, 0x38, 0x01,
0x01, 0x39, 0x45, 0x50, 0x01, 0x4c, 0x01, 0x0a, 0x37, 0x01, 0x01, 0xf7,
0x01, 0x47, 0x45, 0x50, 0x01, 0x3a, 0x38, 0x01, 0x01, 0x10, 0x01, 0x4f,
0x45, 0x50, 0x01, 0x22, 0x38, 0x01, 0x01, 0x1d, 0x46, 0x50, 0x01, 0x12,
0x38, 0x01, 0x01, 0x29, 0x45, 0x50, 0x01, 0x4b, 0x01, 0x07, 0x38, 0x01,
0x01, 0x36, 0x45, 0x50, 0x01, 0x42, 0x01, 0x02, 0x38, 0x01, 0x01, 0xf9,
0x45, 0x50, 0x01, 0x3e, 0x39, 0x01, 0x01, 0x42, 0x45, 0x50, 0x01, 0x3c,
0x39, 0x01, 0x01, 0x46, 0x45, 0x50, 0x01, 0x3b, 0x39, 0x01, 0x01, 0x48,
0x45, 0x50, 0x01, 0xf9, 0x39, 0x01, 0x01, 0x48, 0x45, 0x50, 0x01, 0x3f,
0x01, 0x02, 0x38, 0x01, 0x01, 0x46, 0x45, 0x50, 0x01, 0x48, 0x01, 0xf7,
0x38, 0x01, 0x01, 0x43, 0x45, 0x50, 0x01, 0x4e, 0x01, 0x0e, 0x38, 0x01,
0x01, 0x3f, 0x46, 0x50, 0x01, 0x1c, 0x38, 0x01, 0x01, 0x3a, 0x46, 0x50,
0x01, 0x33, 0x38, 0x01, 0x01, 0x34, 0x46, 0x50, 0x01, 0x46, 0x01, 0x04,
0x37, 0x01, 0x01, 0x2c, 0x47, 0x50, 0x01, 0x19, 0x37, 0x01, 0x01, 0x1f,
0x47, 0x50, 0x01, 0x3a, 0x37, 0x01, 0x01, 0x15, 0x47, 0x50, 0x01, 0x4e,
0x01, 0x11, 0x36, 0x01, 0x01, 0x0a, 0x01, 0xfa, 0x47, 0x50, 0x01, 0x37,
0x36, 0x01, 0x01, 0x02, 0x01, 0x42, 0x47, 0x50, 0x01, 0x4f, 0x01, 0x15,
0x36, 0x01, 0x01, 0x37, 0x48, 0x50, 0x01, 0x42, 0x01, 0x04, 0x35, 0x01,
0x01, 0x25, 0x49, 0x50, 0x01, 0x2c, 0x35, 0x01, 0x01, 0x13, 0x49, 0x50,
0x01, 0x4e, 0x01, 0x15, 0x34, 0x01, 0x01, 0xf7, 0x01, 0x47, 0x49, 0x50,
0x01, 0x48, 0x01, 0x0b, 0x34, 0x01, 0x01, 0x37, 0x4a, 0x50, 0x01, 0x44,
0x01, 0x0a, 0x33, 0x01, 0x01, 0x1f, 0x4b, 0x50, 0x01, 0x44, 0x01, 0x0d,
0x32, 0x01, 0x01, 0x0a, 0x01, 0xfa, 0x4b, 0x50, 0x01, 0x48, 0x01, 0x17,
0x32, 0x01, 0x01, 0x3a, 0x4c, 0x50, 0x01, 0x4f, 0x01, 0x2c, 0x01, 0x04,
0x30, 0x01, 0x01, 0x1f, 0x4e, 0x50, 0x01, 0x41, 0x01, 0x19, 0x2f, 0x01,
0x01, 0x07, 0x01, 0x4a, 0x4e, 0x50, 0x01, 0x44, 0x30, 0x01, 0x01, 0x33,
0x4e, 0x50, 0x01, 0x36, 0x30, 0x01, 0x01, 0x14, 0x4e, 0x50, 0x01, 0x1f,
0x30, 0x01, 0x01, 0x02, 0x01, 0x3f, 0x4c, 0x50, 0x01, 0x4d, 0x01, 0x0b,
0x31, 0x01, 0x01, 0x1e, 0x4c, 0x50, 0x01, 0x3c, 0x32, 0x01, 0x01, 0x04,
0x01, 0x44, 0x4b, 0x50, 0x01, 0x20, 0x33, 0x01, 0x01, 0x20, 0x4a, 0x50,
0x01, 0x4a, 0x01, 0x07, 0x33, 0x01, 0x01, 0x04, 0x01, 0x43, 0x49, 0x50,
0x01, 0x30, 0x35, 0x01, 0x01, 0x1c, 0x48, 0x50, 0x01, 0x4d, 0x01, 0x0e,
0x35, 0x01, 0x01, 0x02, 0x01, 0x3e, 0x47, 0x50, 0x01, 0x36, 0x37, 0x01,
0x01, 0x14, 0x01, 0x4f, 0x45, 0x50, 0x01, 0x4d, 0x01, 0x0e, 0x38, 0x01,
0x01, 0x32, 0x45, 0x50, 0x01, 0x33, 0x39, 0x01, 0x01, 0x07, 0x01, 0x47,
0x43, 0x50, 0x01, 0x4b, 0x01, 0x0b, 0x3a, 0x01, 0x01, 0x1c, 0x43, 0x50,
0x01, 0x26, 0x3c, 0x01, 0x01, 0x37, 0x41, 0x50, 0x01, 0x41, 0x01, 0x04,
0x3c, 0x01, 0x01, 0x08, 0x01, 0x48, 0x3f, 0x50, 0x01, 0x4e, 0x01, 0x13,
0x3e, 0x01, 0x01, 0x19, 0x3f, 0x50, 0x01, 0x2d, 0x40, 0x01, 0x01, 0x2e,
0x3d, 0x50, 0x01, 0x3f, 0x01, 0x03, 0x40, 0x01, 0x01, 0x03, 0x01, 0xf9,
0x3b, 0x50, 0x01, 0x4a, 0x01, 0x0d, 0x42, 0x01, 0x01, 0x09, 0x01, 0x46,
0x39, 0x50, 0x01, 0x4e, 0x01, 0x19, 0x44, 0x01, 0x01, 0x11, 0x01, 0x4b,
0x38, 0x50, 0x01, 0x25, 0x46, 0x01, 0x01, 0x17, 0x01, 0x4d, 0x36, 0x50,
0x01, 0x2e, 0x48, 0x01, 0x01, 0x1b, 0x01, 0x4d, 0x34, 0x50, 0x01, 0x31,
0x4a, 0x01, 0x01, 0x17, 0x01, 0x4a, 0x14, 0x50, 0x01, 0x4d, 0x01, 0x44,
0x01, 0x3b, 0x01, 0x34, 0x01, 0x2e, 0x01, 0x2c, 0x01, 0x2e, 0x01, 0x35,
0x01, 0x3e, 0x01, 0x4a, 0x14, 0x50, 0x01, 0x2e, 0x4c, 0x01, 0x01, 0x0e,
0x01, 0x41, 0x10, 0x50, 0x01, 0x4a, 0x01, 0x37, 0x01, 0x1f, 0x01, 0x0c,
0x01, 0x03, 0x07, 0x01, 0x01, 0x06, 0x01, 0x15, 0x01, 0x2d, 0x01, 0x41,
0x0f, 0x50, 0x01, 0x4a, 0x01, 0x1f, 0x4e, 0x01, 0x01, 0xf7, 0x01, 0x2e,
0x01, 0xfa, 0x0b, 0x50, 0x01, 0x4f, 0x01, 0xf9, 0x01, 0x1e, 0x01, 0x07,
0x0e, 0x01, 0x01, 0x02, 0x01, 0x14, 0x01, 0x31, 0x01, 0x48, 0x0b, 0x50,
0x01, 0x37, 0x01, 0x0c, 0x51, 0x01, 0x01, 0x0d, 0x01, 0x2f, 0x01, 0x45,
0x01, 0x4f, 0x05, 0x50, 0x01, 0x4f, 0x01, 0x43, 0x01, 0x2e, 0x01, 0x11,
0x14, 0x01, 0x01, 0x07, 0x01, 0x1f, 0x01, 0x3c, 0x01, 0x4c, 0x04, 0x50,
0x01, 0x4f, 0x01, 0x46, 0x01, 0x33, 0x01, 0x13, 0x55, 0x01, 0x01, 0x04,
0x01, 0x12, 0x01, 0x1f, 0x01, 0x26, 0x01, 0x28, 0x01, 0x26, 0x01, 0x1e,
0x01, 0x10, 0x01, 0x02, 0x19, 0x01, 0x01, 0x09, 0x01, 0x16, 0x01, 0x1e,
0x01, 0x1f, 0x01, 0x1c, 0x01, 0x11, 0x01, 0x04, 0xff, 0x01, 0xff, 0x01,
0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
0xff, 0x01, 0xb3, 0x01
};
branches/rewrite/i386/boot2/ramdisk.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*
* Supplemental ramdisk functions for the multiboot ramdisk driver.
* Copyright 2009 Tamas Kosarszky. All rights reserved.
*
*/
#include "boot.h"
#include "bootstruct.h"
#include "multiboot.h"
#include "ramdisk.h"
struct multiboot_info * gRAMDiskMI = NULL;
// gRAMDiskVolume holds the bvr for the mounted ramdisk image.
BVRef gRAMDiskVolume = NULL;
bool gRAMDiskBTAliased = false;
char gRAMDiskFile[512];
// Notify OS X that a ramdisk has been setup. XNU with attach this to /dev/md0
void md0Ramdisk()
{
RAMDiskParam ramdiskPtr;
char filename[512];
const char* override_filename = 0;
int fh = -1;
int len;
if(getValueForKey(kMD0Image, &override_filename, &len,
&bootInfo->bootConfig))
{
// Use user specified md0 file
sprintf(filename, "%s", override_filename);
fh = open(filename, 0);
if(fh < 0)
{
sprintf(filename, "rd(0,0)/Extra/%s", override_filename);
fh = open(filename, 0);
if(fh < 0)
{
sprintf(filename, "/Extra/%s", override_filename);
fh = open(filename, 0);
}
}
}
if(fh < 0)
{
sprintf(filename, "rd(0,0)/Extra/Postboot.img");
fh = open(filename, 0);
if(fh < 0)
{
sprintf(filename, "/Extra/Postboot.img");// Check /Extra if not in rd(0,0)
fh = open(filename, 0);
}
}
if (fh >= 0)
{
verbose("Enabling ramdisk %s\n", filename);
ramdiskPtr.size = file_size(fh);
ramdiskPtr.base = AllocateKernelMemory(ramdiskPtr.size);
if(ramdiskPtr.size && ramdiskPtr.base)
{
// Read new ramdisk image contents in kernel memory.
if (read(fh, (char*) ramdiskPtr.base, ramdiskPtr.size) == ramdiskPtr.size)
{
AllocateMemoryRange("RAMDisk", ramdiskPtr.base, ramdiskPtr.size, kBootDriverTypeInvalid);
Node* node = DT__FindNode("/chosen/memory-map", false);
if(node != NULL)
{
DT__AddProperty(node, "RAMDisk", sizeof(RAMDiskParam), (void*)&ramdiskPtr);
}
else
{
verbose("Unable to notify Mac OS X of the ramdisk %s.\n", filename);
}
}
else
{
verbose("Unable to read md0 image %s.\n", filename);
}
}
else
{
verbose("md0 image %s is empty.\n", filename);
}
close(fh);
}
}
void umountRAMDisk()
{
if (gRAMDiskMI != NULL)
{
// Release ramdisk BVRef and DiskBVMap.
struct DiskBVMap *oldMap = diskResetBootVolumes(0x100);
CacheReset();
diskFreeMap(oldMap);
// Free multiboot info and module structures.
if ((void *)gRAMDiskMI->mi_mods_addr != NULL) free((void *)gRAMDiskMI->mi_mods_addr);
if (gRAMDiskMI != NULL) free(gRAMDiskMI);
// Reset multiboot structures.
gMI = gRAMDiskMI = NULL;
*gRAMDiskFile = '\0';
// Release ramdisk driver hooks.
p_get_ramdisk_info = NULL;
p_ramdiskReadBytes = NULL;
// Reset ramdisk bvr
gRAMDiskVolume = NULL;
printf("\nunmounting: done");
}
}
int mountRAMDisk(const char * param)
{
int fh = 0, ramDiskSize;
int error = 0;
// Get file handle for ramdisk file.
fh = open(param, 0);
if (fh != -1)
{
printf("\nreading ramdisk image: %s", param);
ramDiskSize = file_size(fh);
if (ramDiskSize > 0)
{
// Unmount previously mounted image if exists.
umountRAMDisk();
// Read new ramdisk image contents into PREBOOT_DATA area.
if (read(fh, (char *)PREBOOT_DATA, ramDiskSize) != ramDiskSize) error = -1;
}
else error = -1;
close(fh);
}
else error = -1;
if (error == 0)
{
// Save filename in gRAMDiskFile to display information.
strcpy(gRAMDiskFile, param);
// Set gMI as well for the multiboot ramdisk driver hook.
gMI = gRAMDiskMI = malloc(sizeof(multiboot_info));
struct multiboot_module * ramdisk_module = malloc(sizeof(multiboot_module));
// Fill in multiboot info and module structures.
if (gRAMDiskMI != NULL && ramdisk_module != NULL)
{
gRAMDiskMI->mi_mods_count = 1;
gRAMDiskMI->mi_mods_addr = (uint32_t)ramdisk_module;
ramdisk_module->mm_mod_start = PREBOOT_DATA;
ramdisk_module->mm_mod_end = PREBOOT_DATA + ramDiskSize;
// Set ramdisk driver hooks.
p_get_ramdisk_info = &multiboot_get_ramdisk_info;
p_ramdiskReadBytes = &multibootRamdiskReadBytes;
int partCount; // unused
// Save bvr of the mounted image.
gRAMDiskVolume = diskScanBootVolumes(0x100, &partCount);
if(gRAMDiskVolume == NULL)
{
umountRAMDisk();
printf("\nRamdisk contains no partitions.");
}
else
{
char dirSpec[128];
// Reading ramdisk configuration.
strcpy(dirSpec, RAMDISKCONFIG_FILENAME);
if (loadConfigFile(dirSpec, &bootInfo->ramdiskConfig) == 0)
{
getBoolForKey("BTAlias", &gRAMDiskBTAliased, &bootInfo->ramdiskConfig);
}
else
{
printf("\nno ramdisk config...\n");
}
printf("\nmounting: done");
}
}
}
return error;
}
void setRAMDiskBTHook(bool mode)
{
gRAMDiskBTAliased = mode;
if (mode)
{
printf("\nEnabled bt(0,0) alias.");
}
else
{
printf("\nDisabled bt(0,0) alias.");
}
}
void showInfoRAMDisk(void)
{
int len;
const char *val;
if (gRAMDiskMI != NULL)
{
struct multiboot_module * ramdisk_module = (void *)gRAMDiskMI->mi_mods_addr;
printf("\nfile: %s %d", gRAMDiskFile,
ramdisk_module->mm_mod_end - ramdisk_module->mm_mod_start);
printf("\nalias: %s", gRAMDiskBTAliased ? "enabled" : "disabled");
// Display ramdisk information if available.
if (getValueForKey("Info", &val, &len, &bootInfo->ramdiskConfig))
{
printf("\ninfo: %s", val);
}
else
{
printf("\nramdisk info not available.");
}
}
else
{
printf("\nNo ramdisk mounted.");
}
}
int loadPrebootRAMDisk()
{
mountRAMDisk("bt(0,0)/Extra/Preboot.dmg");
if (gRAMDiskMI != NULL)
{
printf("\n");
return 0;
}
else
{
return -1;
}
}
void processRAMDiskCommand(char ** argPtr, const char * cmd)
{
char * ptr = *argPtr;
char param[1024];
getNextArg(&ptr, param);
if (strcmp(cmd, "m") == 0)
{
mountRAMDisk(param);
sleep(2);
}
else if (strcmp(cmd, "u") == 0)
{
umountRAMDisk();
sleep(2);
}
else if (strcmp(cmd, "e") == 0)
{
setRAMDiskBTHook(true);
sleep(2);
}
else if (strcmp(cmd, "d") == 0)
{
setRAMDiskBTHook(false);
sleep(2);
}
else if (strcmp(cmd, "i") == 0)
{
setActiveDisplayPage(1);
clearScreenRows(0, 24);
setCursorPosition(0, 0, 1);
showInfoRAMDisk();
printf("\n\nPress any key to continue.\n");
getchar();
setActiveDisplayPage(0);
}
else
{
setActiveDisplayPage(1);
clearScreenRows(0, 24);
setCursorPosition(0, 0, 1);
printf("\nusage:\n");
printf("\n?rd i - display ramdisk information");
printf("\n?rd m <filename> - mount ramdisk image\n?rd u - unmount ramdisk image");
printf("\n?rd e - enable bt(0,0) alias\n?rd d - disable bt(0,0) alias");
printf("\n\nPress any key to continue.\n");
getchar();
setActiveDisplayPage(0);
}
}
branches/rewrite/i386/boot2/lzss.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 2.0 (the "License"). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/**************************************************************
LZSS.C -- A Data Compression Program
***************************************************************
4/6/1989 Haruhiko Okumura
Use, distribute, and modify this program freely.
Please send me your improved versions.
PC-VAN SCIENCE
NIFTY-Serve PAF01022
CompuServe 74050,1022
**************************************************************/
/*
* lzss.c - Package for decompressing lzss compressed objects
*
* Copyright (c) 2003 Apple Computer, Inc.
*
* DRI: Josh de Cesare
*/
#include <sl.h>
#define N 4096 /* size of ring buffer - must be power of 2 */
#define F 18 /* upper limit for match_length */
#define THRESHOLD 2 /* encode string into position and length
if match_length is greater than this */
#define NIL N /* index for root of binary search trees */
int
decompress_lzss(u_int8_t *dst, u_int8_t *src, u_int32_t srclen)
{
/* ring buffer of size N, with extra F-1 bytes to aid string comparison */
u_int8_t text_buf[N + F - 1];
u_int8_t *dststart = dst;
u_int8_t *srcend = src + srclen;
int i, j, k, r, c;
unsigned int flags;
dst = dststart;
srcend = src + srclen;
for (i = 0; i < N - F; i++)
text_buf[i] = ' ';
r = N - F;
flags = 0;
for ( ; ; ) {
if (((flags >>= 1) & 0x100) == 0) {
if (src < srcend) c = *src++; else break;
flags = c | 0xFF00; /* uses higher byte cleverly */
} /* to count eight */
if (flags & 1) {
if (src < srcend) c = *src++; else break;
*dst++ = c;
text_buf[r++] = c;
r &= (N - 1);
} else {
if (src < srcend) i = *src++; else break;
if (src < srcend) j = *src++; else break;
i |= ((j & 0xF0) << 4);
j = (j & 0x0F) + THRESHOLD;
for (k = 0; k <= j; k++) {
c = text_buf[(i + k) & (N - 1)];
*dst++ = c;
text_buf[r++] = c;
r &= (N - 1);
}
}
}
return dst - dststart;
}
branches/rewrite/i386/boot2/options.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
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
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
/*
* Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* Portions Copyright (c) 1999-2004 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 2.0 (the "License"). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#include "boot.h"
#include "bootstruct.h"
#include "fdisk.h"
#include "ramdisk.h"
#include "gui.h"
#include "embedded.h"
#include "pci.h"
static bool shouldboot = false;
extern int multiboot_timeout;
extern int multiboot_timeout_set;
extern BVRef bvChain;
//extern intmenucount;
extern intgDeviceCount;
intselectIndex = 0;
MenuItem * menuItems = NULL;
enum {
kMenuTopRow = 5,
kMenuMaxItems = 10,
kScreenLastRow = 24
};
//==========================================================================
typedef struct {
int x;
int y;
int type;
} CursorState;
static void changeCursor( int col, int row, int type, CursorState * cs )
{
if (cs) getCursorPositionAndType( &cs->x, &cs->y, &cs->type );
setCursorType( type );
setCursorPosition( col, row, 0 );
}
static void moveCursor( int col, int row )
{
setCursorPosition( col, row, 0 );
}
static void restoreCursor( const CursorState * cs )
{
setCursorPosition( cs->x, cs->y, 0 );
setCursorType( cs->type );
}
//==========================================================================
/* Flush keyboard buffer; returns TRUE if any of the flushed
* characters was F8.
*/
static bool flushKeyboardBuffer(void)
{
bool status = false;
while ( readKeyboardStatus() ) {
if (bgetc() == 0x4200) status = true;
}
return status;
}
//==========================================================================
static int countdown( const char * msg, int row, int timeout )
{
unsigned long time;
int ch = 0;
int col = strlen(msg) + 1;
flushKeyboardBuffer();
if( bootArgs->Video.v_display == VGA_TEXT_MODE )
{
moveCursor( 0, row );
printf(msg);
} else {
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, sizeof(dummy) - 1, true );
drawDeviceIcon( gBootVolume, gui.screen.pixmap, p, true );
drawStrCenteredAt( (char *) msg, &font_small, gui.screen.pixmap, gui.countdown.pos );
// make this screen the new background
memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
}
int multi_buff = 18 * (timeout);
int multi = ++multi_buff;
int lasttime=0;
for ( time = time18(), timeout++; timeout > 0; )
{
if( time18() > lasttime)
{
multi--;
lasttime=time18();
}
if (ch = readKeyboardStatus())
break;
// Count can be interrupted by holding down shift,
// control or alt key
if ( ( readKeyboardShiftFlags() & 0x0F ) != 0 )
{
ch = 1;
break;
}
if ( time18() >= time )
{
time += 18;
timeout--;
if( bootArgs->Video.v_display == VGA_TEXT_MODE )
{
moveCursor( col, row );
printf("(%d) ", timeout);
}
}
if( bootArgs->Video.v_display != VGA_TEXT_MODE )
{
drawProgressBar( gui.screen.pixmap, 100, gui.progressbar.pos , ( multi * 100 / multi_buff ) );
gui.redraw = true;
updateVRAM();
}
}
flushKeyboardBuffer();
return ch;
}
//==========================================================================
char gBootArgs[BOOT_STRING_LEN];
static char * gBootArgsPtr = gBootArgs;
static char * gBootArgsEnd = gBootArgs + BOOT_STRING_LEN - 1;
static char booterCommand[BOOT_STRING_LEN];
static char booterParam[BOOT_STRING_LEN];
static void clearBootArgs(void)
{
gBootArgsPtr = gBootArgs;
memset(gBootArgs, '\0', BOOT_STRING_LEN);
if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
clearGraphicBootPrompt();
}
}
static void addBootArg(const char * argStr)
{
if ( (gBootArgsPtr + strlen(argStr) + 1) < gBootArgsEnd)
{
*gBootArgsPtr++ = ' ';
strcat(gBootArgs, argStr);
gBootArgsPtr += strlen(argStr);
}
}
//==========================================================================
static void showBootPrompt(int row, bool visible)
{
extern char bootPrompt[];
extern char bootRescanPrompt[];
if( bootArgs->Video.v_display == VGA_TEXT_MODE ) {
changeCursor( 0, row, kCursorTypeUnderline, 0 );
clearScreenRows( row, kScreenLastRow );
}
//clearBootArgs();
if (visible) {
if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
if (gEnableCDROMRescan) {
printf( bootRescanPrompt );
} else {
printf( bootPrompt );
printf( gBootArgs );
}
}
} else {
if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
//clearGraphicBootPrompt();
} else {
printf("Press Enter to start up the foreign OS. ");
}
}
}
//==========================================================================
static void updateBootArgs( int key )
{
key &= kASCIIKeyMask;
switch ( key )
{
case kBackspaceKey:
if ( gBootArgsPtr > gBootArgs )
{
*--gBootArgsPtr = '\0';
int x, y, t;
getCursorPositionAndType( &x, &y, &t );
if ( x == 0 && y )
{
x = 80; y--;
}
if (x) x--;
if( bootArgs->Video.v_display == VGA_TEXT_MODE )
{
setCursorPosition( x, y, 0 );
putca(' ', 0x07, 1);
}
else
{
updateGraphicBootPrompt();
}
}
break;
default:
if ( key >= ' ' && gBootArgsPtr < gBootArgsEnd)
{
*gBootArgsPtr++ = key;
if( bootArgs->Video.v_display != VGA_TEXT_MODE ) updateGraphicBootPrompt();
else if ( key >= ' ' && key < 0x7f) putchar(key);
}
break;
}
}
//==========================================================================
static const MenuItem * gMenuItems = NULL;
static int gMenuItemCount;
static int gMenuRow;
static int gMenuHeight;
static int gMenuTop;
static int gMenuBottom;
static int gMenuSelection;
static int gMenuStart;
static int gMenuEnd;
static void printMenuItem( const MenuItem * item, int highlight )
{
printf(" ");
if ( highlight )
putca(' ', 0x70, strlen(item->name) + 4);
else
putca(' ', 0x07, 40);
printf(" %40s\n", item->name);
}
//==========================================================================
static void showMenu( const MenuItem * items, int count,
int selection, int row, int height )
{
int i;
CursorState cursorState;
if ( items == NULL || count == 0 )
return;
// head and tail points to the start and the end of the list.
// top and bottom points to the first and last visible items
// in the menu window.
gMenuItems= items;
gMenuRow= row;
gMenuHeight= height;
gMenuItemCount= count;
gMenuTop= 0;
gMenuBottom= MIN( count, height ) - 1;
gMenuSelection= selection;
gMenuStart= 0;
gMenuEnd = MIN( count, gui.maxdevices ) - 1;
// If the selected item is not visible, shift the list down.
if ( gMenuSelection > gMenuBottom )
{
gMenuTop += ( gMenuSelection - gMenuBottom );
gMenuBottom = gMenuSelection;
}
if ( gMenuSelection > gMenuEnd )
{
gMenuStart += ( gMenuSelection - gMenuEnd );
gMenuEnd = gMenuSelection;
}
// Draw the visible items.
if( bootArgs->Video.v_display != VGA_TEXT_MODE )
drawDeviceList(gMenuStart, gMenuEnd, gMenuSelection);
else {
changeCursor( 0, row, kCursorTypeHidden, &cursorState );
for ( i = gMenuTop; i <= gMenuBottom; i++ )
{
printMenuItem( &items[i], (i == gMenuSelection) );
}
restoreCursor( &cursorState );
}
}
//==========================================================================
static int updateMenu( int key, void ** paramPtr )
{
int moved = 0;
union {
struct {
unsigned int
selectionUp : 1,
selectionDown : 1,
scrollUp : 1,
scrollDown : 1;
} f;
unsigned int w;
} draw = {{0}};
if ( gMenuItems == NULL )
return 0;
if( bootArgs->Video.v_display != VGA_TEXT_MODE )
{
int res;
// set navigation keys for horizontal layout as defaults
int previous= 0x4B00;// left arrow
int subsequent= 0x4D00;// right arrow
int menu= 0x5000;// down arrow
if ( gui.layout == VerticalLayout )
{
// set navigation keys for vertical layout
previous= 0x4800;// up arrow
subsequent= 0x5000;// down arrow
menu= 0x4B00;// right arrow
}
if ( key == previous )
{
if ( gMenuSelection > gMenuTop )
draw.f.selectionUp = 1;
else if ( gMenuTop > 0 )
draw.f.scrollDown = 1;
}
else if ( key == subsequent )
{
if ( gMenuSelection != gMenuBottom)
draw.f.selectionDown = 1;
else if ( gMenuBottom < ( gMenuItemCount - 1 ) )
draw.f.scrollUp = 1;
}
else if ( key == menu )
{
if ( gui.menu.draw )
updateInfoMenu(key);
else
drawInfoMenu();
}
else if ( gui.menu.draw )
{
res = updateInfoMenu(key);
if ( res == CLOSE_INFO_MENU )
gui.menu.draw = false;
else
{
shouldboot = ( res != DO_NOT_BOOT );
if ( shouldboot )
gui.menu.draw = false;
switch (res)
{
case BOOT_NORMAL:
gVerboseMode = false;
gBootMode = kBootModeNormal;
break;
case BOOT_VERBOSE:
gVerboseMode = true;
gBootMode = kBootModeNormal;
addBootArg(kVerboseModeFlag);
break;
case BOOT_IGNORECACHE:
gVerboseMode = false;
gBootMode = kBootModeNormal;
addBootArg(kIgnoreCachesFlag);
break;
case BOOT_SINGLEUSER:
gVerboseMode = true;
gBootMode = kBootModeNormal;
addBootArg(kSingleUserModeFlag);
break;
}
}
}
} else {
switch ( key )
{
case 0x4800: // Up Arrow
if ( gMenuSelection != gMenuTop )
draw.f.selectionUp = 1;
else if ( gMenuTop > 0 )
draw.f.scrollDown = 1;
break;
case 0x5000: // Down Arrow
if ( gMenuSelection != gMenuBottom )
draw.f.selectionDown = 1;
else if ( gMenuBottom < (gMenuItemCount - 1) )
draw.f.scrollUp = 1;
break;
}
}
if ( draw.w )
{
if ( draw.f.scrollUp )
{
scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, 1);
gMenuTop++; gMenuBottom++;
gMenuStart++; gMenuEnd++;
draw.f.selectionDown = 1;
}
if ( draw.f.scrollDown )
{
scollPage(0, gMenuRow, 40, gMenuRow + gMenuHeight - 1, 0x07, 1, -1);
gMenuTop--; gMenuBottom--;
gMenuStart--; gMenuEnd--;
draw.f.selectionUp = 1;
}
if ( draw.f.selectionUp || draw.f.selectionDown )
{
CursorState cursorState;
// Set cursor at current position, and clear inverse video.
if( bootArgs->Video.v_display == VGA_TEXT_MODE )
{
changeCursor( 0, gMenuRow + gMenuSelection - gMenuTop, kCursorTypeHidden, &cursorState );
printMenuItem( &gMenuItems[gMenuSelection], 0 );
}
if ( draw.f.selectionUp )
{
gMenuSelection--;
if(( gMenuSelection - gMenuStart) == -1 )
{
gMenuStart--;
gMenuEnd--;
}
} else {
gMenuSelection++;
if(( gMenuSelection - ( gui.maxdevices - 1) - gMenuStart) > 0 )
{
gMenuStart++;
gMenuEnd++;
}
}
if( bootArgs->Video.v_display == VGA_TEXT_MODE )
{
moveCursor( 0, gMenuRow + gMenuSelection - gMenuTop );
printMenuItem( &gMenuItems[gMenuSelection], 1 );
restoreCursor( &cursorState );
} else
drawDeviceList (gMenuStart, gMenuEnd, gMenuSelection);
}
*paramPtr = gMenuItems[gMenuSelection].param;
moved = 1;
}
return moved;
}
//==========================================================================
static void skipblanks( const char ** cpp )
{
while ( **(cpp) == ' ' || **(cpp) == '\t' ) ++(*cpp);
}
//==========================================================================
static const char * extractKernelName( char ** cpp )
{
char * kn = *cpp;
char * cp = *cpp;
char c;
// Convert char to lower case.
c = *cp | 0x20;
// Must start with a letter or a '/'.
if ( (c < 'a' || c > 'z') && ( c != '/' ) )
return 0;
// Keep consuming characters until we hit a separator.
while ( *cp && (*cp != '=') && (*cp != ' ') && (*cp != '\t') )
cp++;
// Only SPACE or TAB separator is accepted.
// Reject everything else.
if (*cp == '=')
return 0;
// Overwrite the separator, and move the pointer past
// the kernel name.
if (*cp != '\0') *cp++ = '\0';
*cpp = cp;
return kn;
}
//==========================================================================
static void
printMemoryInfo(void)
{
int line;
int i;
MemoryRange *mp = bootInfo->memoryMap;
// Activate and clear page 1
setActiveDisplayPage(1);
clearScreenRows(0, 24);
setCursorPosition( 0, 0, 1 );
printf("BIOS reported memory ranges:\n");
line = 1;
for (i=0; i<bootInfo->memoryMapCount; i++) {
printf("Base 0x%08x%08x, ",
(unsigned long)(mp->base >> 32),
(unsigned long)(mp->base));
printf("length 0x%08x%08x, type %d\n",
(unsigned long)(mp->length >> 32),
(unsigned long)(mp->length),
mp->type);
if (line++ > 20) {
pause();
line = 0;
}
mp++;
}
if (line > 0) {
pause();
}
setActiveDisplayPage(0);
}
char *getMemoryInfoString()
{
int i;
MemoryRange *mp = bootInfo->memoryMap;
char *buff = malloc(sizeof(char)*1024);
if(!buff) return 0;
char info[] = "BIOS reported memory ranges:\n";
sprintf(buff, "%s", info);
for (i=0; i<bootInfo->memoryMapCount; i++) {
sprintf( buff+strlen(buff), "Base 0x%08x%08x, ",
(unsigned long)(mp->base >> 32),
(unsigned long)(mp->base));
sprintf( buff+strlen(buff), "length 0x%08x%08x, type %d\n",
(unsigned long)(mp->length >> 32),
(unsigned long)(mp->length),
mp->type);
mp++;
}
return buff;
}
//==========================================================================
void lspci(void)
{
if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
setActiveDisplayPage(1);
clearScreenRows(0, 24);
setCursorPosition(0, 0, 1);
}
dump_pci_dt(root_pci_dev->children);
pause();
if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
setActiveDisplayPage(0);
}
}
//==========================================================================
int getBootOptions(bool firstRun)
{
int i;
int key;
int nextRow;
int timeout;
int bvCount;
BVRef bvr;
BVRef menuBVR;
bool showPrompt, newShowPrompt, isCDROM;
// Initialize default menu selection entry.
gBootVolume = menuBVR = selectBootVolume(bvChain);
if (biosDevIsCDROM(gBIOSDev)) {
isCDROM = true;
} else {
isCDROM = false;
}
// ensure we're in graphics mode if gui is setup
if (firstRun && gui.initialised && bootArgs->Video.v_display == VGA_TEXT_MODE)
{
setVideoMode(GRAPHICS_MODE, 0);
}
// Clear command line boot arguments
clearBootArgs();
// Allow user to override default timeout.
if (multiboot_timeout_set) {
timeout = multiboot_timeout;
} else if (!getIntForKey(kTimeoutKey, &timeout, &bootInfo->bootConfig)) {
/* If there is no timeout key in the file use the default timeout
which is different for CDs vs. hard disks. However, if not booting
a CD and no config file could be loaded set the timeout
to zero which causes the menu to display immediately.
This way, if no partitions can be found, that is the disk is unpartitioned
or simply cannot be read) then an empty menu is displayed.
If some partitions are found, for example a Windows partition, then
these will be displayed in the menu as foreign partitions.
*/
if (isCDROM) {
timeout = kCDBootTimeout;
} else {
timeout = sysConfigValid ? kBootTimeout : 0;
}
}
if (timeout < 0) {
gBootMode |= kBootModeQuiet;
}
// If the user is holding down a modifier key, enter safe mode.
if ((readKeyboardShiftFlags() & 0x0F) != 0) {
gBootMode |= kBootModeSafe;
}
// Checking user pressed keys
bool f8press = false, spress = false, vpress = false;
while (readKeyboardStatus()) {
key = bgetc ();
if (key == 0x4200) f8press = true;
if ((key & 0xff) == 's' || (key & 0xff) == 'S') spress = true;
if ((key & 0xff) == 'v' || (key & 0xff) == 'V') vpress = true;
}
// If user typed F8, abort quiet mode, and display the menu.
if (f8press) {
gBootMode &= ~kBootModeQuiet;
timeout = 0;
}
// If user typed 'v' or 'V', boot in verbose mode.
if ((gBootMode & kBootModeQuiet) && firstRun && vpress) {
addBootArg(kVerboseModeFlag);
}
// If user typed 's' or 'S', boot in single user mode.
if ((gBootMode & kBootModeQuiet) && firstRun && spress) {
addBootArg(kSingleUserModeFlag);
}
if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
setCursorPosition(0, 0, 0);
clearScreenRows(0, kScreenLastRow);
if (!(gBootMode & kBootModeQuiet)) {
// Display banner and show hardware info.
printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024);
printf(getVBEInfoString());
}
changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);
verbose("Scanning device %x...", gBIOSDev);
}
// When booting from CD, default to hard drive boot when possible.
if (isCDROM && firstRun) {
const char *val;
char *prompt = NULL;
char *name = NULL;
int cnt;
int optionKey;
if (getValueForKey(kCDROMPromptKey, &val, &cnt, &bootInfo->bootConfig)) {
prompt = malloc(cnt + 1);
strncat(prompt, val, cnt);
} else {
name = malloc(80);
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);
}
if (getIntForKey( kCDROMOptionKey, &optionKey, &bootInfo->bootConfig )) {
// The key specified is a special key.
} else {
// Default to F8.
optionKey = 0x4200;
}
// If the timeout is zero then it must have been set above due to the
// early catch of F8 which means the user wants to set boot options
// which we ought to interpret as meaning he wants to boot the CD.
if (timeout != 0) {
key = countdown(prompt, kMenuTopRow, timeout);
} else {
key = optionKey;
}
if (prompt != NULL) {
free(prompt);
}
clearScreenRows( kMenuTopRow, kMenuTopRow + 2 );
// Hit the option key ?
if (key == optionKey) {
gBootMode &= ~kBootModeQuiet;
timeout = 0;
} else {
key = key & 0xFF;
// Try booting hard disk if user pressed 'h'
if (biosDevIsCDROM(gBIOSDev) && key == 'h') {
BVRef bvr;
// Look at partitions hosting OS X other than the CD-ROM
for (bvr = bvChain; bvr; bvr=bvr->next) {
if ((bvr->flags & kBVFlagSystemVolume) && bvr->biosdev != gBIOSDev) {
gBootVolume = bvr;
}
}
}
goto done;
}
}
if (gBootMode & kBootModeQuiet) {
// No input allowed from user.
goto done;
}
if (firstRun && timeout > 0 && countdown("Press any key to enter startup options.", kMenuTopRow, timeout) == 0) {
// If the user is holding down a modifier key,
// enter safe mode.
if ((readKeyboardShiftFlags() & 0x0F) != 0) {
gBootMode |= kBootModeSafe;
}
goto done;
}
if (gDeviceCount) {
// Allocate memory for an array of menu items.
menuItems = malloc(sizeof(MenuItem) * gDeviceCount);
if (menuItems == NULL) {
goto done;
}
// 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, sizeof(menuItems[i].name) - 1, true);
menuItems[i].param = (void *) bvr;
if (bvr == menuBVR) {
selectIndex = i;
}
i--;
}
}
}
if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
// redraw the background buffer
gui.logo.draw = true;
drawBackground();
gui.devicelist.draw = true;
gui.redraw = true;
if (!(gBootMode & kBootModeQuiet)) {
bool showBootBanner = true;
// Check if "Boot Banner"=N switch is present in config file.
getBoolForKey(kBootBannerKey, &showBootBanner, &bootInfo->bootConfig);
if (showBootBanner) {
// Display banner and show hardware info.
gprintf(&gui.screen, bootBanner + 1, (bootInfo->convmem + bootInfo->extmem) / 1024);
}
// redraw background
memcpy(gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4);
}
} else {
// Clear screen and hide the blinking cursor.
clearScreenRows(kMenuTopRow, kMenuTopRow + 2);
changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);
}
nextRow = kMenuTopRow;
showPrompt = true;
if (gDeviceCount) {
if( bootArgs->Video.v_display == VGA_TEXT_MODE ) {
printf("Use \30\31 keys to select the startup volume.");
}
showMenu( menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems );
nextRow += MIN( gDeviceCount, kMenuMaxItems ) + 3;
}
// Show the boot prompt.
showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
showBootPrompt( nextRow, showPrompt );
do {
if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
// redraw background
memcpy( gui.backbuffer->pixels, gui.screen.pixmap->pixels, gui.backbuffer->width * gui.backbuffer->height * 4 );
// reset cursor co-ords
gui.debug.cursor = pos( gui.screen.width - 160 , 10 );
}
key = getchar();
updateMenu( key, (void **) &menuBVR );
newShowPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
if (newShowPrompt != showPrompt) {
showPrompt = newShowPrompt;
showBootPrompt( nextRow, showPrompt );
}
if (showPrompt) {
updateBootArgs(key);
}
switch (key) {
case kReturnKey:
if (gui.menu.draw) {
key=0;
break;
}
if (*gBootArgs == '?') {
char * argPtr = gBootArgs;
// Skip the leading "?" character.
argPtr++;
getNextArg(&argPtr, booterCommand);
getNextArg(&argPtr, booterParam);
/*
* TODO: this needs to be refactored.
*/
if (strcmp( booterCommand, "video" ) == 0) {
if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
showInfoBox(getVBEInfoString(), getVBEModeInfoString());
} else {
printVBEModeInfo();
}
} else if ( strcmp( booterCommand, "memory" ) == 0) {
if (bootArgs->Video.v_display != VGA_TEXT_MODE ) {
showInfoBox("Memory Map", getMemoryInfoString());
} else {
printMemoryInfo();
}
} else if (strcmp(booterCommand, "lspci") == 0) {
lspci();
} else if (strcmp(booterCommand, "more") == 0) {
showTextFile(booterParam);
} else if (strcmp(booterCommand, "rd") == 0) {
processRAMDiskCommand(&argPtr, booterParam);
} else if (strcmp(booterCommand, "norescan") == 0) {
if (gEnableCDROMRescan) {
gEnableCDROMRescan = false;
break;
}
} else {
showHelp();
}
key = 0;
showBootPrompt(nextRow, showPrompt);
break;
}
gBootVolume = menuBVR;
setRootVolume(menuBVR);
gBIOSDev = menuBVR->biosdev;
break;
case kEscapeKey:
clearBootArgs();
break;
case kF5Key:
// New behavior:
// Clear gBootVolume to restart the loop
// if the user enabled rescanning the optical drive.
// Otherwise boot the default boot volume.
if (gEnableCDROMRescan) {
gBootVolume = NULL;
clearBootArgs();
}
break;
case kF10Key:
gScanSingleDrive = false;
scanDisks(gBIOSDev, &bvCount);
gBootVolume = NULL;
clearBootArgs();
break;
case kTabKey:
// New behavior:
// Switch between text & graphic interfaces
// Only Permitted if started in graphics interface
if (useGUI) {
if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
setVideoMode(VGA_TEXT_MODE, 0);
setCursorPosition(0, 0, 0);
clearScreenRows(0, kScreenLastRow);
// Display banner and show hardware info.
printf(bootBanner, (bootInfo->convmem + bootInfo->extmem) / 1024);
printf(getVBEInfoString());
clearScreenRows(kMenuTopRow, kMenuTopRow + 2);
changeCursor(0, kMenuTopRow, kCursorTypeHidden, 0);
nextRow = kMenuTopRow;
showPrompt = true;
if (gDeviceCount) {
printf("Use \30\31 keys to select the startup volume.");
showMenu(menuItems, gDeviceCount, selectIndex, kMenuTopRow + 2, kMenuMaxItems);
nextRow += MIN(gDeviceCount, kMenuMaxItems) + 3;
}
showPrompt = (gDeviceCount == 0) || (menuBVR->flags & kBVFlagNativeBoot);
showBootPrompt(nextRow, showPrompt);
//changeCursor( 0, kMenuTopRow, kCursorTypeUnderline, 0 );
} else {
gui.redraw = true;
setVideoMode(GRAPHICS_MODE, 0);
updateVRAM();
updateGraphicBootPrompt();
}
}
key = 0;
break;
default:
key = 0;
break;
}
} while (0 == key);
done:
if (bootArgs->Video.v_display == VGA_TEXT_MODE) {
clearScreenRows(kMenuTopRow, kScreenLastRow);
changeCursor(0, kMenuTopRow, kCursorTypeUnderline, 0);
}
shouldboot = false;
gui.menu.draw = false;
if (menuItems) {
free(menuItems);
menuItems = NULL;
}
return 0;
}
//==========================================================================
extern unsigned char chainbootdev;
extern unsigned char chainbootflag;
bool copyArgument(const char *argName, const char *val, int cnt, char **argP, int *cntRemainingP)
{
int argLen = argName ? strlen(argName) : 0;
int len = argLen + cnt + 1; // +1 to account for space
if (len > *cntRemainingP) {
error("Warning: boot arguments too long, truncating\n");
return false;
}
if (argName) {
strncpy( *argP, argName, argLen );
*argP += argLen;
*argP[0] = '=';
(*argP)++;
len++; // +1 to account for '='
}
strncpy( *argP, val, cnt );
*argP += cnt;
*argP[0] = ' ';
(*argP)++;
*cntRemainingP -= len;
return true;
}
//
// Returns TRUE if an argument was copied, FALSE otherwise
bool
processBootArgument(
const char *argName, // The argument to search for
const char *userString, // Typed-in boot arguments
const char *kernelFlags, // Kernel flags from config table
const char *configTable,
char **argP, // Output value
int *cntRemainingP, // Output count
char *foundVal // found value
)
{
const char *val;
int cnt;
bool found = false;
if (getValueForBootKey(userString, argName, &val, &cnt)) {
// Don't copy; these values will be copied at the end of argument processing.
found = true;
} else if (getValueForBootKey(kernelFlags, argName, &val, &cnt)) {
// Don't copy; these values will be copied at the end of argument processing.
found = true;
} else if (getValueForKey(argName, &val, &cnt, &bootInfo->bootConfig)) {
copyArgument(argName, val, cnt, argP, cntRemainingP);
found = true;
}
if (found && foundVal) {
strlcpy(foundVal, val, cnt+1);
}
return found;
}
// Maximum config table value size
#define VALUE_SIZE 2048
int
processBootOptions()
{
const char * cp = gBootArgs;
const char * val = 0;
const char * kernel;
int cnt;
int userCnt;
int cntRemaining;
char * argP;
char uuidStr[64];
bool uuidSet = false;
char * configKernelFlags;
char * valueBuffer;
valueBuffer = malloc(VALUE_SIZE);
skipblanks( &cp );
// Update the unit and partition number.
if ( gBootVolume )
{
if (!( gBootVolume->flags & kBVFlagNativeBoot ))
{
readBootSector( gBootVolume->biosdev, gBootVolume->part_boff,
(void *) 0x7c00 );
//
// Setup edx, and signal intention to chain load the
// foreign booter.
//
chainbootdev = gBootVolume->biosdev;
chainbootflag = 1;
return 1;
}
setRootVolume(gBootVolume);
}
// If no boot volume fail immediately because we're just going to fail
// trying to load the config file anyway.
else
return -1;
// Load config table specified by the user, or use the default.
if (!getValueForBootKey(cp, "config", &val, &cnt)) {
val = 0;
cnt = 0;
}
// Load com.apple.Boot.plist from the selected volume
// and use its contents to override default bootConfig.
// This is not a mandatory opeartion anymore.
loadOverrideConfig(&bootInfo->overrideConfig);
// Use the kernel name specified by the user, or fetch the name
// in the config table, or use the default if not specified.
// Specifying a kernel name on the command line, or specifying
// a non-default kernel name in the config file counts as
// overriding the kernel, which causes the kernelcache not
// to be used.
gOverrideKernel = false;
if (( kernel = extractKernelName((char **)&cp) )) {
strcpy( bootInfo->bootFile, kernel );
gOverrideKernel = true;
} else {
if ( getValueForKey( kKernelNameKey, &val, &cnt, &bootInfo->bootConfig ) ) {
strlcpy( bootInfo->bootFile, val, cnt+1 );
if (strcmp( bootInfo->bootFile, kDefaultKernel ) != 0) {
gOverrideKernel = true;
}
} else {
strcpy( bootInfo->bootFile, kDefaultKernel );
}
}
cntRemaining = BOOT_STRING_LEN - 2; // save 1 for NULL, 1 for space
argP = bootArgs->CommandLine;
// Get config table kernel flags, if not ignored.
if (getValueForBootKey(cp, kIgnoreBootFileFlag, &val, &cnt) ||
!getValueForKey( kKernelFlagsKey, &val, &cnt, &bootInfo->bootConfig )) {
val = "";
cnt = 0;
}
configKernelFlags = malloc(cnt + 1);
strlcpy(configKernelFlags, val, cnt + 1);
if (processBootArgument(kBootUUIDKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, 0)) {
// boot-uuid was set either on the command-line
// or in the config file.
uuidSet = true;
} else {
//
// Try an alternate method for getting the root UUID on boot helper partitions.
//
if (gBootVolume->flags & kBVFlagBooter)
{
if((loadHelperConfig(&bootInfo->helperConfig) == 0)
&& getValueForKey(kHelperRootUUIDKey, &val, &cnt, &bootInfo->helperConfig) )
{
getValueForKey(kHelperRootUUIDKey, &val, &cnt, &bootInfo->helperConfig);
copyArgument(kBootUUIDKey, val, cnt, &argP, &cntRemaining);
uuidSet = true;
}
}
if (!uuidSet && gBootVolume->fs_getuuid && gBootVolume->fs_getuuid (gBootVolume, uuidStr) == 0) {
verbose("Setting boot-uuid to: %s\n", uuidStr);
copyArgument(kBootUUIDKey, uuidStr, strlen(uuidStr), &argP, &cntRemaining);
uuidSet = true;
}
}
if (!processBootArgument(kRootDeviceKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gRootDevice)) {
cnt = 0;
if ( getValueForKey( kBootDeviceKey, &val, &cnt, &bootInfo->bootConfig)) {
valueBuffer[0] = '*';
cnt++;
strlcpy(valueBuffer + 1, val, cnt);
val = valueBuffer;
} else {
if (uuidSet) {
val = "*uuid";
cnt = 5;
} else {
// Don't set "rd=.." if there is no boot device key
// and no UUID.
val = "";
cnt = 0;
}
}
if (cnt > 0) {
copyArgument( kRootDeviceKey, val, cnt, &argP, &cntRemaining);
}
strlcpy( gRootDevice, val, (cnt + 1));
}
/*
* Removed. We don't need this anymore.
*
if (!processBootArgument(kPlatformKey, cp, configKernelFlags, bootInfo->config, &argP, &cntRemaining, gPlatformName)) {
getPlatformName(gPlatformName);
copyArgument(kPlatformKey, gPlatformName, strlen(gPlatformName), &argP, &cntRemaining);
}
*/
if (!getValueForBootKey(cp, kSafeModeFlag, &val, &cnt) &&
!getValueForBootKey(configKernelFlags, kSafeModeFlag, &val, &cnt)) {
if (gBootMode & kBootModeSafe) {
copyArgument(0, kSafeModeFlag, strlen(kSafeModeFlag), &argP, &cntRemaining);
}
}
// Store the merged kernel flags and boot args.
cnt = strlen(configKernelFlags);
if (cnt) {
if (cnt > cntRemaining) {
error("Warning: boot arguments too long, truncating\n");
cnt = cntRemaining;
}
strncpy(argP, configKernelFlags, cnt);
argP[cnt++] = ' ';
cntRemaining -= cnt;
}
userCnt = strlen(cp);
if (userCnt > cntRemaining) {
error("Warning: boot arguments too long, truncating\n");
userCnt = cntRemaining;
}
strncpy(&argP[cnt], cp, userCnt);
argP[cnt+userCnt] = '\0';
if(!shouldboot)
{
gVerboseMode = getValueForKey( kVerboseModeFlag, &val, &cnt, &bootInfo->bootConfig ) ||
getValueForKey( kSingleUserModeFlag, &val, &cnt, &bootInfo->bootConfig );
gBootMode = ( getValueForKey( kSafeModeFlag, &val, &cnt, &bootInfo->bootConfig ) ) ?
kBootModeSafe : kBootModeNormal;
if ( getValueForKey( kIgnoreCachesFlag, &val, &cnt, &bootInfo->bootConfig ) ) {
gBootMode = kBootModeSafe;
}
}
if ( getValueForKey( kMKextCacheKey, &val, &cnt, &bootInfo->bootConfig ) )
{
strlcpy(gMKextName, val, cnt + 1);
}
free(configKernelFlags);
free(valueBuffer);
return 0;
}
//==========================================================================
// Load the help file and display the file contents on the screen.
static void showTextBuffer(char *buf, int size)
{
char*bp;
intline;
intline_offset;
intc;
if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
showInfoBox( "Press q to quit\n",buf );
return;
}
bp = buf;
while (size-- > 0) {
if (*bp == '\n') {
*bp = '\0';
}
bp++;
}
*bp = '\1';
line_offset = 0;
setActiveDisplayPage(1);
while (1) {
clearScreenRows(0, 24);
setCursorPosition(0, 0, 1);
bp = buf;
for (line = 0; *bp != '\1' && line < line_offset; line++) {
while (*bp != '\0') {
bp++;
}
bp++;
}
for (line = 0; *bp != '\1' && line < 23; line++) {
setCursorPosition(0, line, 1);
printf("%s\n", bp);
while (*bp != '\0') {
bp++;
}
bp++;
}
setCursorPosition(0, 23, 1);
if (*bp == '\1') {
printf("[Type %sq or space to quit viewer]", (line_offset > 0) ? "p for previous page, " : "");
} else {
printf("[Type %s%sq to quit viewer]", (line_offset > 0) ? "p for previous page, " : "", (*bp != '\1') ? "space for next page, " : "");
}
c = getchar();
if (c == 'q' || c == 'Q') {
break;
}
if ((c == 'p' || c == 'P') && line_offset > 0) {
line_offset -= 23;
}
if (c == ' ') {
if (*bp == '\1') {
break;
} else {
line_offset += 23;
}
}
}
setActiveDisplayPage(0);
}
void showHelp(void)
{
if (bootArgs->Video.v_display != VGA_TEXT_MODE) {
showInfoBox("Help. Press q to quit.\n", (char *)BootHelp_txt);
} else {
showTextBuffer((char *)BootHelp_txt, BootHelp_txt_len);
}
}
void showTextFile(const char * filename)
{
#define MAX_TEXT_FILE_SIZE 65536
char*buf;
intfd;
intsize;
if ((fd = open_bvdev("bt(0,0)", filename, 0)) < 0) {
printf("\nFile not found: %s\n", filename);
sleep(2);
return;
}
size = file_size(fd);
if (size > MAX_TEXT_FILE_SIZE) {
size = MAX_TEXT_FILE_SIZE;
}
buf = malloc(size);
read(fd, buf, size);
close(fd);
showTextBuffer(buf, size);
free(buf);
}
// This is a very simplistic prompting scheme that just grabs two hex characters
// Eventually we need to do something more user-friendly like display a menu
// based off of the Multiboot device list
int selectAlternateBootDevice(int bootdevice)
{
int key;
int newbootdevice;
int digitsI = 0;
char *end;
char digits[3] = {0,0,0};
// We've already printed the current boot device so user knows what it is
printf("Typical boot devices are 80 (First HD), 81 (Second HD)\n");
printf("Enter two-digit hexadecimal boot device [%02x]: ", bootdevice);
do {
key = getchar();
switch (key & kASCIIKeyMask) {
case kBackspaceKey:
if (digitsI > 0) {
int x, y, t;
getCursorPositionAndType(&x, &y, &t);
// Assume x is not 0;
x--;
setCursorPosition(x,y,0); // back up one char
// Overwrite with space without moving cursor position
putca(' ', 0x07, 1);
digitsI--;
} else {
// TODO: Beep or something
}
break;
case kReturnKey:
digits[digitsI] = '\0';
newbootdevice = strtol(digits, &end, 16);
if (end == digits && *end == '\0') {
// User entered empty string
printf("\nUsing default boot device %x\n", bootdevice);
key = 0;
} else if(end != digits && *end == '\0') {
bootdevice = newbootdevice;
printf("\n");
key = 0; // We gots da boot device
} else {
printf("\nCouldn't parse. try again: ");
digitsI = 0;
}
break;
default:
if (isxdigit(key & kASCIIKeyMask) && digitsI < 2) {
putchar(key & kASCIIKeyMask);
digits[digitsI++] = key & kASCIIKeyMask;
} else {
// TODO: Beep or something
}
break;
};
} while (key != 0);
return bootdevice;
}
bool promptForRescanOption(void)
{
printf("\nWould you like to enable media rescan option?\nPress ENTER to enable or any key to skip.\n");
if (getchar() == kReturnKey) {
return true;
} else {
return false;
}
}
branches/rewrite/i386/boot2/graphic_utils.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/* Graphic utility functions and data types
* Prashant Vaibhav (C) 12/12/2008
* Chameleon
*/
#include "boot.h"
#include "graphic_utils.h"
#include "gui.h"
void blend( const pixmap_t *blendThis, // Source image
pixmap_t *blendInto, // Dest image
const position_t position) // Where to place the source image
{
uint16_t sx, sy, dx, dy;
uint32_t dstrb, dstag, srcrb, srcag, drb, dag, rb, ag, alpha;
uint16_t width = (blendThis->width + position.x < blendInto->width) ? blendThis->width: blendInto->width-position.x;
uint16_t height = (blendThis->height + position.y < blendInto->height) ? blendThis->height: blendInto->height-position.y;
for (dy = position.y, sy = 0; sy < height; dy++, sy++) {
for (dx = position.x, sx = 0; sx < width; dx++, sx++) {
alpha = (pixel(blendThis, sx, sy).ch.a);
/* Skip blending for fully transparent pixel */
if (alpha == 0) continue;
/* For fully opaque pixel, there is no need to interpolate */
if (alpha == 255) {
pixel(blendInto, dx, dy).value = pixel(blendThis, sx, sy).value;
continue;
}
/* For semi-transparent pixels, do a full blend */
//alpha++
/* This is needed to spread the alpha over [0..256] instead of [0..255]
Boundary conditions were handled above */
dstrb = pixel(blendInto, dx, dy).value & 0xFF00FF;
dstag = (pixel(blendInto, dx, dy).value >> 8) & 0xFF00FF;
srcrb = pixel(blendThis, sx, sy).value & 0xFF00FF;
srcag = (pixel(blendThis, sx, sy).value >> 8) & 0xFF00FF;
drb = srcrb - dstrb;
dag = srcag - dstag;
drb *= alpha; dag *= alpha;
drb >>= 8; dag >>= 8;
rb = (drb + dstrb) & 0x00FF00FF;
ag = ((dag + dstag) << 8) & 0xFF00FF00;
pixel(blendInto, dx, dy).value = (rb | ag);
}
}
}
position_t centeredIn( const pixmap_t *background, const pixmap_t *toCenter )
{
position_t centered;
centered.x = ( background->width - toCenter->width ) / 2;
centered.y = ( background->height - toCenter->height ) / 2;
return centered;
}
position_t centeredAt( const pixmap_t *pixmap, const position_t center )
{
position_t topleft;
topleft.x = center.x - (pixmap->width / 2);
topleft.y = center.y - (pixmap->height / 2);
return topleft;
}
position_t pos(const uint16_t x, const uint16_t y) { position_t p; p.x = x; p.y = y; return p; }
void flipRB(pixmap_t *p)
{
//if(testForQemu()) return;
uint32_t x;
register uint8_t tempB;
for (x = 0; x < (p->height) * (p->width) ; x++) {
tempB = (p->pixels[x]).ch.b;
(p->pixels[x]).ch.b = (p->pixels[x]).ch.r;
(p->pixels[x]).ch.r = tempB;
}
}
branches/rewrite/i386/boot2/mboot.c
5050
5151
5252
53
53
5454
5555
5656
......
329329
330330
331331
332
333
332
333
334334
335335
336336
337337
338
338
339339
340340
341341
342342
343343
344
344
345345
346346
347347
......
420420
421421
422422
423
424
425
426
423
427424
428425
429426
......
464461
465462
466463
467
464
468465
469466
470467
......
496493
497494
498495
496
unsigned int byteoff,
unsigned int byteCount, void * buffer );
int multiboot_get_ramdisk_info(int biosdev, struct driveInfo *dip);
static long multiboot_LoadExtraDrivers(FileLoadDrivers_t FileLoadDrivers_p);
//static long multiboot_LoadExtraDrivers(FileLoadDrivers_t FileLoadDrivers_p);
// Starts off in the multiboot context 1 MB high but eventually gets into low memory
// and winds up with a bootdevice in eax which is all that boot() wants
*/
boot_args temporaryBootArgsData;
bzero(&temporaryBootArgsData, sizeof(boot_args));
bootArgs = &temporaryBootArgsData;
bootArgs->Video.v_display = VGA_TEXT_MODE;
// bootArgs = &temporaryBootArgsData;
// bootArgs->Video.v_display = VGA_TEXT_MODE;
// Install ramdisk and extra driver hooks
p_get_ramdisk_info = &multiboot_get_ramdisk_info;
p_ramdiskReadBytes = &multibootRamdiskReadBytes;
LoadExtraDrivers_p = &multiboot_LoadExtraDrivers;
//LoadExtraDrivers_p = &multiboot_LoadExtraDrivers;
// Since we call multiboot ourselves, its return address will be correct.
// That is unless it's inlined in which case it does not matter.
uint32_t bootdevice = multiboot(multiboot_magic, mi_p);
// We're about to exit and temporaryBootArgs will no longer be valid
bootArgs = NULL;
//bootArgs = NULL;
return bootdevice;
}
}
}
}
if(doSelectDevice)
{
bootdevice = selectAlternateBootDevice(bootdevice);
}
if(bootdevice == BAD_BOOT_DEVICE)
sleep(2); // pause for a second before halting
return bootdevice;
dip->valid = true;
return 0;
}
#if 0
static long multiboot_LoadExtraDrivers(FileLoadDrivers_t FileLoadDrivers_p)
{
char extensionsSpec[1024];
}
return 0;
}
#endif
branches/rewrite/i386/boot2/boot.c
5555
5656
5757
58
59
6058
6159
6260
6361
6462
65
66
67
63
6864
6965
7066
......
7268
7369
7470
75
7671
7772
7873
......
8075
8176
8277
83
84
85
86
87
88
89
9078
9179
9280
......
130118
131119
132120
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
235
236
237121
238122
239123
......
258142
259143
260144
261
262
263
264
265
266
267
268
269
145
146
270147
271
272
273
274
275
276
277
278
279
280
281
282
283148
284149
285150
286
287
288
289151
290
291
292
293152
153
154
294155
295156
296157
297158
298159
160
299161
162
300163
301164
302
303
165
304166
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343167
344168
345169
346170
347
171
348172
349173
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
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
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
174
#include "fake_efi.h"
#include "sl.h"
#include "libsa.h"
#include "ramdisk.h"
#include "gui.h"
#include "platform.h"
#include "modules.h"
long gBootMode; /* defaults to 0 == kBootModeNormal */
bool gOverrideKernel;
static char gBootKernelCacheFile[512];
static char gCacheNameAdler[64 + 256];
char *gPlatformName = gCacheNameAdler;
char *gPlatformName;
char gRootDevice[512];
char gMKextName[512];
char gMacOSVersion[8];
bool gScanSingleDrive;
int bvCount = 0;
//intmenucount = 0;
int gDeviceCount = 0;
BVRef bvr;
BVRef bvChain;
bool useGUI;
//static void selectBiosDevice(void);
static unsigned long Adler32(unsigned char *buffer, long length);
static bool checkOSVersion(const char * version);
static bool getOSVersion();
static bool gUnloadPXEOnExit = false;
/*
* How long to wait (in seconds) to load the
* kernel after displaying the "boot:" prompt.
}
//==========================================================================
// execKernel - Load the kernel image (mach-o) and jump to its entry point.
static int ExecKernel(void *binary)
{
entry_t kernelEntry;
int ret;
bootArgs->kaddr = bootArgs->ksize = 0;
execute_hook("ExecKernel", (void*)binary, NULL, NULL, NULL);
ret = DecodeKernel(binary,
&kernelEntry,
(char **) &bootArgs->kaddr,
(int *)&bootArgs->ksize );
if ( ret != 0 )
return ret;
// Reserve space for boot args
reserveKernBootStruct();
// Notify modules that the kernel has been decoded
execute_hook("DecodedKernel", (void*)binary, NULL, NULL, NULL);
// Load boot drivers from the specifed root path.
if (!gHaveKernelCache)
LoadDrivers("/");
clearActivityIndicator();
if (gErrors) {
printf("Errors encountered while starting up the computer.\n");
printf("Pausing %d seconds...\n", kBootErrorTimeout);
sleep(kBootErrorTimeout);
}
setupFakeEfi();
md0Ramdisk();
verbose("Starting Darwin %s\n",( archCpuType == CPU_TYPE_I386 ) ? "x86" : "x86_64");
// Cleanup the PXE base code.
if ( (gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit ) {
if ( (ret = nbpUnloadBaseCode()) != nbpStatusSuccess )
{
printf("nbpUnloadBaseCode error %d\n", (int) ret);
sleep(2);
}
}
bool dummyVal;
if (getBoolForKey(kWaitForKeypressKey, &dummyVal, &bootInfo->bootConfig) && dummyVal) {
printf("Press any key to continue...");
getchar();
}
usb_loop();
if (checkOSVersion("10.7"))
{
execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgs, NULL, NULL);// Notify modules that the kernel is about to be started
}
else
{
execute_hook("Kernel Start", (void*)kernelEntry, (void*)bootArgsPreLion, NULL, NULL);// Notify modules that the kernel is about to be started
}
// If we were in text mode, switch to graphics mode.
// This will draw the boot graphics unless we are in
// verbose mode.
if(gVerboseMode)
setVideoMode( GRAPHICS_MODE, 0 );
else
drawBootGraphics();
setupBooterLog();
finalizeBootStruct();
if (checkOSVersion("10.7")) {
// Masking out so that Lion doesn't doublefault
outb(0x21, 0xff);/* Maskout all interrupts Pic1 */
outb(0xa1, 0xff);/* Maskout all interrupts Pic2 */
// Jump to kernel's entry point. There's no going back now.
startprog( kernelEntry, bootArgs );
}
else {
// Jump to kernel's entry point. There's no going back now.
startprog( kernelEntry, bootArgsPreLion );
}
// Not reached
return 0;
}
//==========================================================================
// This is the entrypoint from real-mode which functions exactly as it did
// before. Multiboot does its own runtime initialization, does some of its
// own things, and then calls common_boot.
// next boot device on its list.
void common_boot(int biosdev)
{
int status;
char *bootFile;
unsigned long adler32;
bool quiet;
bool firstRun = true;
bool instantMenu;
bool rescanPrompt;
unsigned int allowBVFlags = kBVFlagSystemVolume|kBVFlagForeignBoot;
unsigned int denyBVFlags = kBVFlagEFISystem;
//unsigned int allowBVFlags = kBVFlagSystemVolume|kBVFlagForeignBoot;
// unsigned int denyBVFlags = kBVFlagEFISystem;
// Set reminder to unload the PXE base code. Neglect to unload
// the base code will result in a hang or kernel panic.
gUnloadPXEOnExit = true;
// Record the device that the booter was loaded from.
gBIOSDev = biosdev & kBIOSDevMask;
// Initialize boot info structure.
initKernBootStruct();
initBooterLog();
// Setup VGA text mode.
// Not sure if it is safe to call setVideoMode() before the
// config table has been loaded. Call video_mode() instead.
#if DEBUG
printf("before video_mode\n");
#endif
video_mode( 2 ); // 80x25 mono text mode.
#if DEBUG
printf("after video_mode\n");
#endif
// TOOD: move to a module
/*
// Scan and record the system's hardware information.
scan_platform();
// First get info for boot volume.
scanBootVolumes(gBIOSDev, 0);
bvChain = getBVChainForBIOSDev(gBIOSDev);
setBootGlobals(bvChain);
// Load boot.plist config file
status = loadSystemConfig(&bootInfo->bootConfig);
scanDisks(gBIOSDev, &bvCount);
if (getBoolForKey(kQuietBootKey, &quiet, &bootInfo->bootConfig) && quiet) {
gBootMode |= kBootModeQuiet;
}
// Override firstRun to get to the boot menu instantly by setting "Instant Menu"=y in system config
if (getBoolForKey(kInsantMenuKey, &instantMenu, &bootInfo->bootConfig) && instantMenu) {
firstRun = false;
}
// Loading preboot ramdisk if exists.
loadPrebootRAMDisk();
// Disable rescan option by default
gEnableCDROMRescan = false;
// Enable it with Rescan=y in system config
if (getBoolForKey(kRescanKey, &gEnableCDROMRescan, &bootInfo->bootConfig) && gEnableCDROMRescan) {
gEnableCDROMRescan = true;
}
// Ask the user for Rescan option by setting "Rescan Prompt"=y in system config.
rescanPrompt = false;
if (getBoolForKey(kRescanPromptKey, &rescanPrompt , &bootInfo->bootConfig) && rescanPrompt && biosDevIsCDROM(gBIOSDev)) {
gEnableCDROMRescan = promptForRescanOption();
}
// Enable touching a single BIOS device only if "Scan Single Drive"=y is set in system config.
if (getBoolForKey(kScanSingleDriveKey, &gScanSingleDrive, &bootInfo->bootConfig) && gScanSingleDrive) {
gScanSingleDrive = true;
}
// Create a list of partitions on device(s).
if (gScanSingleDrive) {
scanBootVolumes(gBIOSDev, &bvCount);
} else {
scanDisks(gBIOSDev, &bvCount);
}
// Create a separated bvr chain using the specified filters.
bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
gBootVolume = selectBootVolume(bvChain);
*/
// Intialize module system
init_module_system();
#if DEBUG
printf(" Default: %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBootVolume, gBootVolume->biosdev, gBootVolume->part_no, gBootVolume->flags);
printf(" bt(0,0): %d, ->biosdev: %d, ->part_no: %d ->flags: %d\n", gBIOSBootVolume, gBIOSBootVolume->biosdev, gBIOSBootVolume->part_no, gBIOSBootVolume->flags);
getchar();
#endif
useGUI = true;
// Override useGUI default
getBoolForKey(kGUIKey, &useGUI, &bootInfo->bootConfig);
if (useGUI && initGUI())
{
// initGUI() returned with an error, disabling GUI.
useGUI = false;
}
setBootGlobals(bvChain);
// Parse args, load and start kernel.
while (1) {
const char *val;
int len;
int trycache;
long flags, cachetime, kerneltime, exttime, sleeptime, time;
int ret = -1;
void *binary = (void *)kLoadAddr;
bool tryresume;
bool tryresumedefault;
bool forceresume;
bool usecache;
// additional variable for testing alternate kernel image locations on boot helper partitions.
char bootFileSpec[512];
// Initialize globals.
sysConfigValid = false;
gErrors = false;
status = getBootOptions(firstRun);
firstRun = false;
if (status == -1) continue;
status = processBootOptions();
// Status==1 means to chainboot
if ( status == 1 ) break;
// Status==-1 means that the config file couldn't be loaded or that gBootVolume is NULL
if ( status == -1 )
{
// gBootVolume == NULL usually means the user hit escape.
if(gBootVolume == NULL)
{
freeFilteredBVChain(bvChain);
if (gEnableCDROMRescan)
rescanBIOSDevice(gBIOSDev);
bvChain = newFilteredBVChain(0x80, 0xFF, allowBVFlags, denyBVFlags, &gDeviceCount);
setBootGlobals(bvChain);
setupDeviceList(&bootInfo->themeConfig);
}
continue;
}
// Other status (e.g. 0) means that we should proceed with boot.
// Turn off any GUI elements
if( bootArgs->Video.v_display == GRAPHICS_MODE )
{
gui.devicelist.draw = false;
gui.bootprompt.draw = false;
gui.menu.draw = false;
gui.infobox.draw = false;
gui.logo.draw = false;
drawBackground();
updateVRAM();
}
// Find out which version mac os we're booting.
getOSVersion();
if (platformCPUFeature(CPU_FEATURE_EM64T)) {
archCpuType = CPU_TYPE_X86_64;
} else {
archCpuType = CPU_TYPE_I386;
}
if (getValueForKey(karch, &val, &len, &bootInfo->bootConfig)) {
if (strncmp(val, "i386", 4) == 0) {
archCpuType = CPU_TYPE_I386;
}
}
// Notify moduals that we are attempting to boot
execute_hook("PreBoot", NULL, NULL, NULL, NULL);
if (!getBoolForKey (kWake, &tryresume, &bootInfo->bootConfig)) {
tryresume = true;
tryresumedefault = true;
} else {
tryresumedefault = false;
}
if (!getBoolForKey (kForceWake, &forceresume, &bootInfo->bootConfig)) {
forceresume = false;
}
if (forceresume) {
tryresume = true;
tryresumedefault = false;
}
while (tryresume) {
const char *tmp;
BVRef bvr;
if (!getValueForKey(kWakeImage, &val, &len, &bootInfo->bootConfig))
val="/private/var/vm/sleepimage";
// Do this first to be sure that root volume is mounted
ret = GetFileInfo(0, val, &flags, &sleeptime);
if ((bvr = getBootVolumeRef(val, &tmp)) == NULL)
break;
// Can't check if it was hibernation Wake=y is required
if (bvr->modTime == 0 && tryresumedefault)
break;
if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat))
break;
if (!forceresume && ((sleeptime+3)<bvr->modTime)) {
printf ("Hibernate image is too old by %d seconds. Use ForceWake=y to override\n",bvr->modTime-sleeptime);
break;
}
HibernateBoot((char *)val);
break;
}
if(getBoolForKey(kUseKernelCache, &usecache, &bootInfo->bootConfig)) {
if (getValueForKey(kKernelCacheKey, &val, &len, &bootInfo->bootConfig)) {
strlcpy(gBootKernelCacheFile, val, len+1);
}
else {
//Lion
if (checkOSVersion("10.7")) {
sprintf(gBootKernelCacheFile, "%skernelcache", kDefaultCachePathSnow);
}
// Snow Leopard
else if (checkOSVersion("10.6")) {
sprintf(gBootKernelCacheFile, "kernelcache_%s", (archCpuType == CPU_TYPE_I386) ? "i386" : "x86_64");
int lnam = sizeof(gBootKernelCacheFile) + 9; //with adler32
//Slice - TODO ???
// e.g. kernelcache_i386.E102928C.qSs0 = "unsaved" cache file.
//
// See kext_tools-180.2.1/kextcache_main.c:
// "Source directory has changed since starting; "
// "not saving cache file %s."
// or
// "Source kernel has changed since starting; "
// "not saving cache file %s."
char* name;
long prev_time = 0;
struct dirstuff* cacheDir = opendir(kDefaultCachePathSnow);
while(readdir(cacheDir, (const char**)&name, &flags, &time) >= 0)
{
if(((flags & kFileTypeMask) != kFileTypeDirectory) && time > prev_time && strstr(name, gBootKernelCacheFile) && (name[lnam] != '.'))
{
sprintf(gBootKernelCacheFile, "%s%s", kDefaultCachePathSnow, name);
prev_time = time;
}
}
}
else {
// Reset cache name.
bzero(gCacheNameAdler + 64, sizeof(gCacheNameAdler) - 64);
sprintf(gCacheNameAdler + 64, "%s,%s", gRootDevice, bootInfo->bootFile);
adler32 = Adler32((unsigned char *)gCacheNameAdler, sizeof(gCacheNameAdler));
sprintf(gBootKernelCacheFile, "%s.%08lX", kDefaultCachePathLeo, adler32);
}
}
}
// Check for cache file.
trycache = (usecache &&
((gBootMode & kBootModeSafe) == 0) &&
!gOverrideKernel &&
(gBootFileType == kBlockDeviceType) &&
(gMKextName[0] == '\0') &&
(gBootKernelCacheFile[0] != '\0'));
verbose("Loading Darwin %s\n", gMacOSVersion);
if (trycache) do {
// if we haven't found the kernel yet, don't use the cache
ret = GetFileInfo(NULL, bootInfo->bootFile, &flags, &kerneltime);
if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
trycache = 0;
break;
}
ret = GetFileInfo(NULL, gBootKernelCacheFile, &flags, &cachetime);
if ((ret != 0) || ((flags & kFileTypeMask) != kFileTypeFlat)
|| (cachetime < kerneltime)) {
trycache = 0;
break;
}
ret = GetFileInfo("/System/Library/", "Extensions", &flags, &exttime);
if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)
&& (cachetime < exttime)) {
trycache = 0;
break;
}
if (kerneltime > exttime) {
exttime = kerneltime;
}
if (cachetime != (exttime + 1)) {
trycache = 0;
break;
}
} while (0);
do {
if (trycache) {
bootFile = gBootKernelCacheFile;
verbose("Loading kernel cache %s\n", bootFile);
if (checkOSVersion("10.7")) {
ret = LoadThinFatFile(bootFile, &binary);
}
else {
ret = LoadFile(bootFile);
binary = (void *)kLoadAddr;
}
if (ret >= 0)
break;
verbose("Kernel cache did not loaded %s\n ", bootFile);
}
bootFile = bootInfo->bootFile;
// Try to load kernel image from alternate locations on boot helper partitions.
sprintf(bootFileSpec, "com.apple.boot.P/%s", bootFile);
ret = GetFileInfo(NULL, bootFileSpec, &flags, &time);
if (ret == -1)
{
sprintf(bootFileSpec, "com.apple.boot.R/%s", bootFile);
ret = GetFileInfo(NULL, bootFileSpec, &flags, &time);
if (ret == -1)
{
sprintf(bootFileSpec, "com.apple.boot.S/%s", bootFile);
ret = GetFileInfo(NULL, bootFileSpec, &flags, &time);
if (ret == -1)
{
// No alternate location found, using the original kernel image path.
strcpy(bootFileSpec, bootFile);
}
}
}
if (checkOSVersion("10.7"))
{
//Lion, dont load kernel if haz cache
if (!trycache) {
verbose("Loading kernel %s\n", bootFileSpec);
ret = LoadThinFatFile(bootFileSpec, &binary);
if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) {
archCpuType = CPU_TYPE_I386;
ret = LoadThinFatFile(bootFileSpec, &binary);
}
}
else ret = 1;
}
else {
//Snow Leopard or older
verbose("Loading kernel %s\n", bootFileSpec);
ret = LoadThinFatFile(bootFileSpec, &binary);
if (ret <= 0 && archCpuType == CPU_TYPE_X86_64) {
archCpuType = CPU_TYPE_I386;
ret = LoadThinFatFile(bootFileSpec, &binary);
}
}
} while (0);
clearActivityIndicator();
#if DEBUG
printf("Pausing...");
sleep(8);
#endif
if (ret <= 0) {
printf("Can't find %s\n", bootFile);
sleep(1);
if (gBootFileType == kNetworkDeviceType) {
// Return control back to PXE. Don't unload PXE base code.
gUnloadPXEOnExit = false;
break;
}
} else {
/* Won't return if successful. */
ret = ExecKernel(binary);
}
}
// chainboot
if (status==1) {
if (getVideoMode() == GRAPHICS_MODE) {// if we are already in graphics-mode,
setVideoMode(VGA_TEXT_MODE, 0);// switch back to text mode
}
}
if ((gBootFileType == kNetworkDeviceType) && gUnloadPXEOnExit) {
nbpUnloadBaseCode();
}
}
/*!
Selects a new BIOS device, taking care to update the global state appropriately.
*/
/*
static void selectBiosDevice(void)
{
struct DiskBVMap *oldMap = diskResetBootVolumes(gBIOSDev);
CacheReset();
diskFreeMap(oldMap);
oldMap = NULL;
int dev = selectAlternateBootDevice(gBIOSDev);
BVRef bvchain = scanBootVolumes(dev, 0);
BVRef bootVol = selectBootVolume(bvchain);
gBootVolume = bootVol;
setRootVolume(bootVol);
gBIOSDev = dev;
}
*/
bool checkOSVersion(const char * version)
{
return ((gMacOSVersion[0] == version[0]) && (gMacOSVersion[1] == version[1]) && (gMacOSVersion[2] == version[2]) && (gMacOSVersion[3] == version[3]));
}
bool getOSVersion()
{
bool valid = false;
config_file_t systemVersion;
const char *val;
int len;
if (!loadConfigFile("System/Library/CoreServices/SystemVersion.plist", &systemVersion))
{
valid = true;
}
else if (!loadConfigFile("System/Library/CoreServices/ServerVersion.plist", &systemVersion))
{
valid = true;
}
if (valid)
{
if (getValueForKey(kProductVersion, &val, &len, &systemVersion))
{
// getValueForKey uses const char for val
// so copy it and trim
*gMacOSVersion = '\0';
strncat(gMacOSVersion, val, MIN(len, 4));
}
else
valid = false;
}
return valid;
}
#define BASE 65521L /* largest prime smaller than 65536 */
#define NMAX 5000
// NMAX (was 5521) the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
unsigned long Adler32(unsigned char *buf, long len)
{
unsigned long s1 = 1; // adler & 0xffff;
unsigned long s2 = 0; // (adler >> 16) & 0xffff;
unsigned long result;
int k;
while (len > 0) {
k = len < NMAX ? len : NMAX;
len -= k;
while (k >= 16) {
DO16(buf);
buf += 16;
k -= 16;
}
if (k != 0) do {
s1 += *buf++;
s2 += s1;
} while (--k);
s1 %= BASE;
s2 %= BASE;
}
result = (s2 << 16) | s1;
return OSSwapHostToBigInt32(result);
}
}
branches/rewrite/i386/boot2/Cconfig
1212
1313
1414
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
15
Say Y here if you want to enable debug mode for the
module system.
source "i386/modules/Cconfig"
config EMBED_THEME
bool "Embed Theme"
default n
---help---
Say Y here if you want compile in a default theme.
config EMBEDED_THEME
string "Theme name"
default "embed"
depends on EMBED_THEME
---help---
Specify the name of the theme to compile in.
source "i386/modules/Cconfig"
branches/rewrite/i386/boot2/Makefile
4242
4343
4444
45
46
47
48
45
46
4947
5048
5149
# The ordering is important;
# boot2.o must be first.
OBJS = boot2.o boot.o graphics.o drivers.o prompt.o options.o lzss.o mboot.o \
ramdisk.o picopng.o resume.o bmdecompress.o graphic_utils.o gui.o modules.o \
modules_support.o boot_modules.o
# button.o browser.o scrollbar.o == NOTYET
OBJS = boot2.o boot.o mboot.o modules.o modules_support.o boot_modules.o
# button.o browser.o scrollbar.o == NOTYET bmdecompress.o graphic_utils.o prompt.o options.o lzss.o
UTILDIR = ../util
DIRS_NEEDED = $(OBJROOT) $(SYMROOT)

Archive Download the corresponding diff file

Revision: 1065