Chameleon

Chameleon Commit Details

Date:2012-10-29 15:03:38 (6 years 7 months ago)
Author:armel cadet-petit
Commit:2112
Parents: 2111
Message:updated libsa, security fixes, replaced strcmp by strncmp in most cases
Changes:
D/branches/cparm/i386/libsa/bzero.s
D/branches/cparm/i386/libsa/bcopy.s
A/branches/cparm/i386/libsa/memset.s
A/branches/cparm/i386/libsa/strlcpy.s
A/branches/cparm/i386/libsa/strncpy.s
A/branches/cparm/i386/libsa/strlcat.s
A/branches/cparm/i386/libsa/memset_pattern_sse2.s
A/branches/cparm/i386/libsa/strcpy.s
A/branches/cparm/i386/libsa/strncmp.s
A/branches/cparm/i386/libsa/bcopy_scalar.s
A/branches/cparm/i386/libsa/bzero_scalar.s
A/branches/cparm/i386/libsa/strlen.s
A/branches/cparm/i386/libsa/strcmp.s
A/branches/cparm/i386/libsa/memcmp.s
A/branches/cparm/i386/libsa/__bzero.s
M/branches/cparm/i386/libsaio/modules.h
M/branches/cparm/i386/libsa/string.c
M/branches/cparm/i386/libsaio/load.c
M/branches/cparm/i386/modules/SMBiosGetters/mysmbios.c
M/branches/cparm/i386/libsaio/platform.c
M/branches/cparm/Chameleon.xcodeproj/project.pbxproj
M/branches/cparm/i386/modules/GraphicsEnabler/nvidia.c
M/branches/cparm/i386/libsaio/disk.c
M/branches/cparm/i386/modules/SMBiosPatcher/smbios_patcher.c
M/branches/cparm/i386/boot2/options.c
M/branches/cparm/i386/libsaio/xml.c
M/branches/cparm/i386/modules/GUI/GUI_module.c
M/branches/cparm/i386/libsa/Makefile
M/branches/cparm/i386/util/machOconv.c
M/branches/cparm/i386/modules/ACPICodec/acpi_codec.c
M/branches/cparm/CHANGES
M/branches/cparm/i386/libsaio/device_tree.c
M/branches/cparm/i386/modules/Keymapper/Keymapper.c
M/branches/cparm/i386/boot2/drivers.c
M/branches/cparm/i386/MakeInc.dir
M/branches/cparm/xcode3_sym.zip
M/branches/cparm/i386/modules/GraphicsEnabler/gma.c
M/branches/cparm/i386/libsa/memory.h
M/branches/cparm/i386/modules/KextPatcher/kext_patcher.c
M/branches/cparm/i386/libsaio/fake_efi.c
M/branches/cparm/i386/util/md.c
M/branches/cparm/i386/modules/Resolution/915resolution.c
M/branches/cparm/i386/modules/GUI/gui.c
M/branches/cparm/i386/modules/RamDiskLoader/ramdisk.c
M/branches/cparm/i386/boot2/boot.c
M/branches/cparm/i386/libsaio/modules.c
M/branches/cparm/i386/modules/Keymapper/Keylayout.c
M/branches/cparm/i386/util/fdisk/user.c

File differences

branches/cparm/Chameleon.xcodeproj/project.pbxproj
3030
3131
3232
33
34
35
36
37
38
39
40
41
42
43
44
3345
3446
3547
......
461473
462474
463475
464
465
466476
467477
468478
......
470480
471481
472482
483
473484
474485
475486
......
9931004
9941005
9951006
996
997
1007
1008
1009
9981010
999
1000
1001
1002
1003
10041011
10051012
10061013
10071014
10081015
1016
1017
1018
1019
10091020
1021
10101022
1023
10111024
1025
1026
1027
1028
1029
1030
1031
10121032
10131033
1034
1035
10141036
10151037
10161038
AB021459161C3B9F007F5325 /* user.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user.h; sourceTree = "<group>"; };
AB02145A161C3B9F007F5325 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = "<group>"; };
AB0E930C14C6223500F798D7 /* cpu_intel_amd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cpu_intel_amd.c; sourceTree = "<group>"; };
AB19DD0816392AFD00CF3455 /* __bzero.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = __bzero.s; sourceTree = "<group>"; };
AB19DD3A1639360E00CF3455 /* strcmp.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = strcmp.s; sourceTree = "<group>"; };
AB19DD451639370A00CF3455 /* strcpy.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = strcpy.s; sourceTree = "<group>"; };
AB19DD461639375500CF3455 /* strlcat.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = strlcat.s; sourceTree = "<group>"; };
AB19DD47163937C800CF3455 /* strlcpy.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = strlcpy.s; sourceTree = "<group>"; };
AB19DD481639382000CF3455 /* strlen.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = strlen.s; sourceTree = "<group>"; };
AB19DD491639389500CF3455 /* strncmp.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = strncmp.s; sourceTree = "<group>"; };
AB19DD4A163938D300CF3455 /* strncpy.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = strncpy.s; sourceTree = "<group>"; };
AB19DD4B16393A1500CF3455 /* memcmp.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = memcmp.s; sourceTree = "<group>"; };
AB19DD5D16393CD800CF3455 /* memset.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = memset.s; sourceTree = "<group>"; };
AB19DD6616393D6400CF3455 /* memset_pattern_sse2.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = memset_pattern_sse2.s; sourceTree = "<group>"; };
AB19DD6B16393E1400CF3455 /* bzero_scalar.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = bzero_scalar.s; sourceTree = "<group>"; };
AB22095D15334C9E00AA9851 /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = md5.h; sourceTree = "<group>"; };
AB3117CF15DBCBDE00DA0817 /* fake_crt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fake_crt.c; sourceTree = "<group>"; };
AB42D02115187F2C0078E84A /* background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = background.png; sourceTree = "<group>"; };
AB43B3E414C37E530018D529 /* Symbols.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Symbols.c; sourceTree = "<group>"; };
AB43B3E514C37E530018D529 /* WKdm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKdm.h; sourceTree = "<group>"; };
AB43B3E614C37E530018D529 /* WKdmDecompress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = WKdmDecompress.c; sourceTree = "<group>"; };
AB43B3EC14C383120018D529 /* bcopy.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = bcopy.s; sourceTree = "<group>"; };
AB43B3ED14C383120018D529 /* bzero.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = bzero.s; sourceTree = "<group>"; };
AB43B3EE14C383120018D529 /* divdi3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = divdi3.c; sourceTree = "<group>"; };
AB43B3EF14C383120018D529 /* moddi3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = moddi3.c; sourceTree = "<group>"; };
AB43B3F014C383120018D529 /* qdivrem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = qdivrem.c; sourceTree = "<group>"; };
AB43B3F214C383120018D529 /* udivdi3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = udivdi3.c; sourceTree = "<group>"; };
AB43B3F314C383120018D529 /* umoddi3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = umoddi3.c; sourceTree = "<group>"; };
AB43B3F814C384040018D529 /* stack_protector.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stack_protector.c; sourceTree = "<group>"; };
AB6DE3E6163976A80065E17F /* bcopy_scalar.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = bcopy_scalar.s; sourceTree = "<group>"; };
AB79217514F38CF200F5EB39 /* bootXnu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bootXnu.h; sourceTree = "<group>"; };
AB79219214F3919E00F5EB39 /* ModuleHelp.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ModuleHelp.txt; sourceTree = "<group>"; };
ABA0C7BF1568190C003440AF /* arc4random-fbsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "arc4random-fbsd.c"; sourceTree = "<group>"; };
AB43B2DE14C37E520018D529 /* libsa */ = {
isa = PBXGroup;
children = (
AB43B3EC14C383120018D529 /* bcopy.s */,
AB43B3ED14C383120018D529 /* bzero.s */,
AB6DE3E6163976A80065E17F /* bcopy_scalar.s */,
AB19DD0816392AFD00CF3455 /* __bzero.s */,
AB19DD6B16393E1400CF3455 /* bzero_scalar.s */,
AB43B3EE14C383120018D529 /* divdi3.c */,
AB43B3EF14C383120018D529 /* moddi3.c */,
AB43B3F014C383120018D529 /* qdivrem.c */,
AB43B3F114C383120018D529 /* quad.h */,
AB43B3F214C383120018D529 /* udivdi3.c */,
AB43B3F314C383120018D529 /* umoddi3.c */,
AB43B2DF14C37E520018D529 /* efi_tables.c */,
AB43B2E014C37E520018D529 /* efi_tables.h */,
AB43B2E214C37E520018D529 /* libsa.h */,
AB43B2E314C37E520018D529 /* Makefile */,
AB43B2E414C37E520018D529 /* memory.h */,
AB19DD4B16393A1500CF3455 /* memcmp.s */,
AB19DD5D16393CD800CF3455 /* memset.s */,
AB19DD6616393D6400CF3455 /* memset_pattern_sse2.s */,
AB43B3EF14C383120018D529 /* moddi3.c */,
AB43B2E614C37E520018D529 /* printf.c */,
AB43B3F014C383120018D529 /* qdivrem.c */,
AB43B2E714C37E520018D529 /* qsort.c */,
AB43B3F114C383120018D529 /* quad.h */,
AB43B2E914C37E520018D529 /* setjmp.s */,
AB19DD3A1639360E00CF3455 /* strcmp.s */,
AB19DD451639370A00CF3455 /* strcpy.s */,
AB19DD461639375500CF3455 /* strlcat.s */,
AB19DD47163937C800CF3455 /* strlcpy.s */,
AB19DD481639382000CF3455 /* strlen.s */,
AB19DD491639389500CF3455 /* strncmp.s */,
AB19DD4A163938D300CF3455 /* strncpy.s */,
AB43B2EA14C37E520018D529 /* string.c */,
AB43B2EB14C37E520018D529 /* strtol.c */,
AB43B3F214C383120018D529 /* udivdi3.c */,
AB43B3F314C383120018D529 /* umoddi3.c */,
AB43B2EC14C37E520018D529 /* zalloc.c */,
);
path = libsa;
branches/cparm/CHANGES
11
2
3
4
25
6
7
38
49
510
- Security fixes
- Using of optimized version for bcopy, bzero, strcmp, strcpy, strncpy, strlcat, strlcpy, strlen, strncmp, memset and memcmp
- Replaced strcmp (deprecated and unsecure) by strncmp as far as possible
- Decided to keep ld_classic to keep the compatibility with the apple's compiler from snow leopard (xcode 3.x) to Mountain lion (xcode 4.5) (in fact this has not changed since the last commit ;-) )
- Security fixes
- Few security fixes
- Fixed a serious bug in picopng
- Fixed a bug in gui.c, related to the images loading
branches/cparm/i386/libsaio/xml.c
305305
306306
307307
308
308
309309
310310
311311
......
318318
319319
320320
321
321
322322
323323
324324
325325
326326
327
327
328328
329329
330330
......
398398
399399
400400
401
401
402402
403403
404404
......
477477
478478
479479
480
480
481481
482482
483483
......
485485
486486
487487
488
488
489489
490490
491491
......
497497
498498
499499
500
500
501501
502502
503503
504504
505
505
506506
507507
508508
509509
510510
511
511
512512
513513
514514
......
516516
517517
518518
519
519
520520
521521
522522
length = 0;
}
/***** dict ****/
else if (!strcmp(tagName, kXMLTagDict))
else if (!strncmp(tagName, kXMLTagDict, sizeof(kXMLTagDict)))
{
length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);
}
length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);
}
/***** key ****/
else if (!strcmp(tagName, kXMLTagKey))
else if (!strncmp(tagName, kXMLTagKey, sizeof(kXMLTagKey)))
{
length = ParseTagKey(buffer + pos, tag);
}
/***** string ****/
else if (!strcmp(tagName, kXMLTagString))
else if (!strncmp(tagName, kXMLTagString, sizeof(kXMLTagString)))
{
length = ParseTagString(buffer + pos, tag);
}
}
/***** integer ****/
else if (!strcmp(tagName, kXMLTagInteger))
else if (!strncmp(tagName, kXMLTagInteger, sizeof(kXMLTagInteger)))
{
length = ParseTagInteger(buffer + pos, tag);
}
}
/***** data ****/
else if (!strcmp(tagName, kXMLTagData))
else if (!strncmp(tagName, kXMLTagData, sizeof(kXMLTagData)))
{
length = ParseTagData(buffer + pos, tag);
}
{
length = ParseTagData(buffer + pos, tag);
}
else if (!strcmp(tagName, kXMLTagDate))
else if (!strncmp(tagName, kXMLTagDate, sizeof(kXMLTagDate)))
{
length = ParseTagDate(buffer + pos, tag);
}
}
/***** false ****/
else if (!strcmp(tagName, kXMLTagFalse))
else if (!strncmp(tagName, kXMLTagFalse, sizeof(kXMLTagFalse)))
{
length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse);
}
/***** true ****/
else if (!strcmp(tagName, kXMLTagTrue))
else if (!strncmp(tagName, kXMLTagTrue, sizeof(kXMLTagTrue)))
{
length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue);
}
/***** array ****/
else if (!strcmp(tagName, kXMLTagArray))
else if (!strncmp(tagName, kXMLTagArray, sizeof(kXMLTagArray) ))
{
length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
}
{
length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
}
else if (!strcmp(tagName, kXMLTagArray "/"))
else if (!strncmp(tagName, kXMLTagArray "/", strlen(kXMLTagArray "/")))
{
length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1);
}
branches/cparm/i386/libsaio/device_tree.c
311311
312312
313313
314
314
315315
316316
317317
......
384384
385385
386386
387
387
388388
389389
390390
//DPRINTF("Node properties = 0x%x\n", node->properties);
for (prop = node->properties; prop; prop = prop->next) {
//DPRINTF("Prop '%s'\n", prop->name);
if (strcmp(prop->name, "name") == 0) {
if (strncmp(prop->name, "name",sizeof("name")) == 0) {
return prop->value;
}
}
for (prop = node->properties; prop; prop = prop->next) {
char c = *((char *)prop->value);
if (prop->length < 64 && (
strcmp(prop->name, "name") == 0 ||
strncmp(prop->name, "name",sizeof("name") ) == 0 ||
(c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') || c == '_')) {
branches/cparm/i386/libsaio/modules.c
195195
196196
197197
198
198
199199
200200
201201
202202
203203
204204
205
205
206206
207207
208208
......
269269
270270
271271
272
272
273273
274
275
276
277
278
274279
275280
276281
277282
278
279
283
284
285
280286
281287
282288
......
284290
285291
286292
287
293
288294
289295
296
290297
291298
292299
......
412419
413420
414421
422
415423
424
425
426
416427
428
417429
430
418431
419432
420433
......
424437
425438
426439
440
427441
442
428443
429444
430445
......
432447
433448
434449
450
435451
452
436453
437454
455
438456
439457
440458
441459
442460
443461
462
444463
445464
446465
......
477496
478497
479498
480
499
481500
482501
483502
......
509528
510529
511530
512
531
513532
514533
515534
......
519538
520539
521540
522
541
542
523543
524544
525545
526546
527547
528548
529
549
530550
531551
532552
......
558578
559579
560580
561
581
562582
563583
564584
......
570590
571591
572592
573
593
594
574595
575596
576597
......
605626
606627
607628
629
608630
609
631
632
633
610634
611635
612636
......
9911015
9921016
9931017
994
1018
9951019
9961020
9971021
......
10241048
10251049
10261050
1027
1051
10281052
10291053
10301054
......
10481072
10491073
10501074
1051
1075
10521076
10531077
10541078
......
10961120
10971121
10981122
1099
1123
11001124
11011125
11021126
......
11591183
11601184
11611185
1186
11621187
1188
1189
1190
11631191
1192
11641193
1165
1194
11661195
11671196
11681197
......
11911220
11921221
11931222
1194
1223
11951224
11961225
11971226
......
12321261
12331262
12341263
1235
1264
12361265
12371266
12381267
......
12481277
12491278
12501279
1251
1280
12521281
1282
1283
1284
12531285
12541286
12551287
......
12581290
12591291
12601292
1261
1293
12621294
1295
12631296
12641297
12651298
12661299
12671300
12681301
1269
1302
12701303
12711304
12721305
12731306
12741307
12751308
1309
12761310
1311
1312
1313
1314
12771315
12781316
12791317
......
13011339
13021340
13031341
1342
13041343
13051344
13061345
......
13081347
13091348
13101349
1311
1350
13121351
13131352
13141353
......
13211360
13221361
13231362
1363
13241364
13251365
13261366
......
15521592
15531593
15541594
1555
1595
15561596
15571597
15581598
......
20342074
20352075
20362076
2037
2077
20382078
20392079
20402080
20412081
2042
2082
20432083
20442084
20452085
// Make sure this is not a directory.
if ((flags & kFileTypeMask) == kFileTypeDirectory) continue;
if ((strcmp("Symbols.dylib",name)) == 0) continue; // if we found Symbols.dylib, just skip it
if ((strncmp("Symbols.dylib",name, sizeof("Symbols.dylib"))) == 0) continue; // if we found Symbols.dylib, just skip it
if (is_dylib_loaded(name) == EFI_SUCCESS) continue;
// Make sure this is a kext.
length = strlen(name);
if (strcmp(name + length - 6, ".dylib")) continue;
if (strncmp(name + length - 6, ".dylib", 6)) continue;
char *tmp = newStringWithFormat( "/Extra/modules/%s",name);
if (!tmp) {
module_base = (char*) malloc(moduleSize);
}
if (module_base && read(fh, module_base, moduleSize) == moduleSize)
if (!module_base)
{
goto out;
}
if (read(fh, module_base, moduleSize) == moduleSize)
{
DBG("Module %s read in.\n", module);
// Module loaded into memory, parse it
module_start = parse_mach(name, module_base, &add_symbol);
module_start = parse_mach(name, module_base, &add_symbol);
}
else
{
#if DEBUG_MODULES
getc();
#endif
module_start = 0xFFFFFFFF;
free(module_base);
}
}
out:
close(fh);
return module_start;
}
* symbols will still be available (TODO: fix this). This should not
* happen as all dependencies are verified before the sybols are read in.
*/
#if macho_64
unsigned int parse_mach(char *module, void* binary, long long(*symbol_handler)(char*, char*, long long, char))// TODO: add param to specify valid archs
#else
unsigned int parse_mach(char *module, void* binary, long long(*symbol_handler)(char*, char*, long long))// TODO: add param to specify valid archs
#endif
{
#if macho_64
char is64 = false;
#endif
unsigned int module_start = 0xFFFFFFFF;
EFI_STATUS bind_status = EFI_SUCCESS;
{
struct segment_command *segCommand = NULL;
#if macho_64
struct segment_command_64 *segCommand64 = NULL;
#endif
struct load_command *loadCommand = NULL;
UInt32 binaryIndex = 0;
UInt16 cmd = 0;
// Parse through the load commands
if(((struct mach_header*)binary)->magic == MH_MAGIC)
{
#if macho_64
is64 = false;
#endif
binaryIndex += sizeof(struct mach_header);
}
#if macho_64
else if(((struct mach_header_64*)binary)->magic == MH_MAGIC_64)
{
// NOTE: modules cannot be 64bit...
is64 = true;
binaryIndex += sizeof(struct mach_header_64);
}
#endif
else
{
printf("Modules: Invalid mach magic\n");
//printf("Segment name is %s\n", segCommand->segname);
if(strcmp("__TEXT", segCommand->segname) == 0)
if(strncmp("__TEXT", segCommand->segname, sizeof("__TEXT")) == 0)
{
UInt32 sectionIndex;
sectionIndex += sizeof(struct section);
if(strcmp("__text", sect->sectname) == 0)
if(strncmp("__text", sect->sectname,sizeof("__text")) == 0)
{
// __TEXT,__text found, save the offset and address for when looking for the calls.
textSection = sect->offset;
}
}
break;
}
}
#if macho_64
case LC_SEGMENT_64:// 64bit macho's
{
segCommand64 = binary + binaryIndex;
//printf("Segment name is %s\n", segCommand->segname);
if(strcmp("__TEXT", segCommand64->segname) == 0)
if(strncmp("__TEXT", segCommand64->segname, sizeof("__TEXT")) == 0)
{
UInt32 sectionIndex;
sectionIndex += sizeof(struct section_64);
if(strcmp("__text", sect->sectname) == 0)
if(strncmp("__text", sect->sectname, sizeof("__text")) == 0)
{
// __TEXT,__text found, save the offset and address for when looking for the calls.
textSection = sect->offset;
}
break;
}
}
#endif
case LC_DYSYMTAB:
break;
}
// bind_macho uses the symbols.
#if macho_64
module_start = handle_symtable(module, (UInt32)binary, symtabCommand, symbol_handler, is64);
#else
module_start = handle_symtable(module, (UInt32)binary, symtabCommand, symbol_handler);
#endif
// Rebase the module before binding it.
if(dyldInfoCommand && dyldInfoCommand->rebase_off)
{
bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);
}
else if(symbolName && (strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0))
else if(symbolName && (strncmp(symbolName, SYMBOL_DYLD_STUB_BINDER,sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0))
{
printf("Unable to bind symbol %s needed by %s\n", symbolName, module);
getc();
bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);
}
else if(symbolName && (strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0))
else if(symbolName && (strncmp(symbolName, SYMBOL_DYLD_STUB_BINDER,sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0))
{
printf("Unable to bind symbol %s needed by %s\n", symbolName, module);
getc();
bind_location((UInt32*)address, (char*)symbolAddr, addend, BIND_TYPE_POINTER);
}
else if(symbolName && (strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0))
else if(symbolName && (strncmp(symbolName, SYMBOL_DYLD_STUB_BINDER,sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0))
{
printf("Unable to bind symbol %s needed by %s\n", symbolName, module);
getc();
segmentAddress += tmp2 + sizeof(void*);
}
}
else if(symbolName && (strcmp(symbolName, SYMBOL_DYLD_STUB_BINDER) != 0))
else if(symbolName && (strncmp(symbolName, SYMBOL_DYLD_STUB_BINDER,sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0))
{
printf("Unable to bind symbol %s needed by %s\n", symbolName, module);
getc();
* adjust it's internal symbol list (sort) to optimize locating new symbols
* NOTE: returns the address if the symbol is "start", else returns 0xFFFFFFFF
*/
#if macho_64
long long add_symbol(char* module,char* symbol, long long addr, char is64)
#else
long long add_symbol(char* module,char* symbol, long long addr)
#endif
{
#if macho_64
if(is64) return 0xFFFFFFFF; // Fixme
#endif
// This only can handle 32bit symbols
symbolList_t* new_entry= malloc(sizeof(symbolList_t));
DBG("Adding symbol %s at 0x%X\n", symbol, addr);
do {
if ((module != NULL) && (strcmp(module,SYMBOLS_BUNDLE) != 0))
if ((module != NULL) && (strncmp(module,SYMBOLS_BUNDLE,sizeof(SYMBOLS_BUNDLE)) != 0))
break;
if(lookup_symbol && (UInt32)lookup_symbol != 0xFFFFFFFF)
}
#if DEBUG_MODULES
if(strcmp(name, SYMBOL_DYLD_STUB_BINDER) != 0)
if(strncmp(name, SYMBOL_DYLD_STUB_BINDER, sizeof(SYMBOL_DYLD_STUB_BINDER)) != 0)
{
verbose("Unable to locate symbol %s\n", name);
getc();
* parse the symbol table
* Lookup any undefined symbols
*/
#if macho_64
unsigned int handle_symtable(char *module, UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, char*, long long, char), char is64)
#else
unsigned int handle_symtable(char *module, UInt32 base, struct symtab_command* symtabCommand, long long(*symbol_handler)(char*, char*, long long))
#endif
{
unsigned int module_start = 0xFFFFFFFF;
return 0xFFFFFFFF;
}
char* symbolString = base + (char*)symtabCommand->stroff;
//char* symbolTable = base + symtabCommand->symoff;
#if macho_64
if(!is64)
#endif
{
struct nlist* symbolEntry = (void*)base + symtabCommand->symoff;
while(symbolIndex < symtabCommand->nsyms)
{
if(symbolEntry->n_value)
{
if(strstr(symbolString + symbolEntry->n_un.n_strx, "module_start") || (strcmp(symbolString + symbolEntry->n_un.n_strx, "start") == 0))
if(strstr(symbolString + symbolEntry->n_un.n_strx, "module_start") || (strncmp(symbolString + symbolEntry->n_un.n_strx, "start", sizeof("start")) == 0))
{
module_start = base + symbolEntry->n_value;
DBG("n_value %x module_start %x\n", (unsigned)symbolEntry->n_value, (unsigned)module_start);
}
else
{
#if macho_64
symbol_handler(module, symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value, is64);
#else
symbol_handler(module, symbolString + symbolEntry->n_un.n_strx, (long long)base + symbolEntry->n_value);
#endif
}
#if DEBUG_MODULES
bool isTexT = (((unsigned)symbolEntry->n_value > (unsigned)vmaddr) && ((unsigned)(vmaddr + vmsize) > (unsigned)symbolEntry->n_value ));
symbolIndex++;// TODO remove
}
}
#if macho_64
else
{
struct nlist_64* symbolEntry = (void*)base + symtabCommand->symoff;
while(symbolIndex < symtabCommand->nsyms)
{
if(strstr(symbolString + symbolEntry->n_un.n_strx, "module_start") || (strcmp(symbolString + symbolEntry->n_un.n_strx, "start") == 0))
if(strstr(symbolString + symbolEntry->n_un.n_strx, "module_start") || (strncmp(symbolString + symbolEntry->n_un.n_strx, "start",sizeof("start")) == 0))
{
module_start = (unsigned int)(base + symbolEntry->n_value);
}
symbolIndex++;// TODO remove
}
}
#endif
return module_start;
// Make sure this is a kext.
length = strlen(name);
if (strcmp(name + length - 7, ".bundle")) continue;
if (strncmp(name + length - 7, ".bundle",7)) continue;
// Save the file name.
strlcpy(gFileName, name, DEFAULT_BUNDLE_SPEC_SIZE);
prop = XMLGetProperty(moduleDict, kPropNSPrincipalClass);
if ((prop != 0) && prop->string)
{
if (!strcmp(prop->string,SYSLIB_CLASS))
if (!strncmp(prop->string,SYSLIB_CLASS, sizeof(SYSLIB_CLASS)))
{
tmpModule->willLoad = BundlePrioritySystemLib;
break;
}
if (!strcmp(prop->string,SYS_CLASS))
if (!strncmp(prop->string,SYS_CLASS, sizeof(SYS_CLASS)))
{
tmpModule->willLoad = BundlePrioritySystem;
break;
branches/cparm/i386/libsaio/modules.h
2424
2525
2626
27
2728
28
2929
3030
3131
......
8080
8181
8282
83
8384
85
86
87
8488
89
8590
91
92
93
8694
95
8796
8897
8998
9099
100
101
102
103
104
91105
92106
93107
#include "efi.h"
#define DEFAULT_BUNDLE_SPEC_SIZE 4096
#define macho_64 1
extern unsigned long long textAddress;
extern unsigned long long textSection;
void rebase_macho(void* base, char* rebase_stream, UInt32 size);
EFI_STATUS bind_macho(char* module, void* base, char* bind_stream, UInt32 size);
#if macho_64
long long add_symbol(char* module,char* symbol, long long addr, char is64);
#else
long long add_symbol(char* module,char* symbol, long long addr);
#endif
#if macho_64
unsigned int parse_mach(char *module, void* binary, long long(*symbol_handler)(char*, char*, long long, char));
#else
unsigned int parse_mach(char *module, void* binary, long long(*symbol_handler)(char*, char*, long long));
#endif
#if macho_64
unsigned int handle_symtable(char *module, UInt32 base,
struct symtab_command* symtabCommand,
long long(*symbol_handler)(char*, char*, long long, char),
char is64);
#else
unsigned int handle_symtable(char *module, UInt32 base,
struct symtab_command* symtabCommand,
long long(*symbol_handler)(char*, char*, long long));
#endif
unsigned int lookup_all_symbols(const char* module, const char* name);
branches/cparm/i386/libsaio/load.c
272272
273273
274274
275
275
276276
277277
278278
stop("Kernel overflows available space");
}
if (vmsize && (strcmp(segname, "__PRELINK") == 0 || strcmp(segname, "__PRELINK_INFO") == 0))
if (vmsize && (strncmp(segname, "__PRELINK", sizeof("__PRELINK")) == 0 || strncmp(segname, "__PRELINK_INFO", sizeof("__PRELINK_INFO")) == 0))
safe_set_env(envgHaveKernelCache, true);
// Copy from file load area.
branches/cparm/i386/libsaio/platform.c
393393
394394
395395
396
396
397397
398398
399399
struct env_struct *current_var;
for(current_var=platform_env;current_var;current_var=(struct env_struct*)(current_var->hh.next))
{
if (strcmp(current_var->name, envConsoleErr) == 0) {
if (strncmp(current_var->name, envConsoleErr, sizeof(envConsoleErr)) == 0) {
if (current_var->Type == kEnvPtr) {
printf("stderr: %s \n",(char*)(uint32_t)current_var->ptr);
}
branches/cparm/i386/libsaio/disk.c
265265
266266
267267
268
268
269269
270270
271271
272272
273273
274
274
275275
276276
277277
......
11621162
11631163
11641164
1165
1165
11661166
11671167
11681168
......
17061706
17071707
17081708
1709
17091710
17101711
17111712
......
17201721
17211722
17221723
1723
1724
1724
1725
17251726
17261727
17271728
1728
1729
1730
1731
17291732
17301733
17311734
......
17401743
17411744
17421745
1743
1746
17441747
17451748
17461749
static const char * bios_error(int errnum)
{
static char errorstr[] = "Error 0x00";
static char errorstr[11];
const char * errname;
errname = getNameForValue( bios_errors, errnum );
if ( errname ) return errname;
sprintf(errorstr, "Error 0x%02x", errnum);
snprintf(errorstr, sizeof(errorstr), "Error 0x%02x", errnum);
return errorstr; // No string, print error code only
}
dpme.dpme_boot_block);
*/
if (strcmp(dpme_p->dpme_type, "Apple_HFS") == 0) {
if (strncmp(dpme_p->dpme_type, "Apple_HFS",sizeof("Apple_HFS")) == 0) {
bvr = newAPMBVRef(biosdev,
i,
OSSwapBigToHostInt32(dpme_p->dpme_pblock_start) * factor,
#ifdef BOOT_HELPER_SUPPORT
int ret;
char label[BVSTRLEN];
char dirSpec[256];
int fh, fileSize, error;
#endif
for (bvr = chain; bvr < (BVRef)ULONG_MAX; bvr = bvr->next) {
//
if (bvr->flags & kBVFlagBooter)
{
sprintf(dirSpec, "hd(%d,%d)/System/Library/CoreServices/", BIOS_DEV_UNIT(bvr), bvr->part_no);
strcpy(fileSpec, ".disk_label.contentDetails");
snprintf(dirSpec, sizeof(dirsSpec),"hd(%d,%d)/System/Library/CoreServices/", BIOS_DEV_UNIT(bvr), bvr->part_no);
strlcpy(fileSpec, ".disk_label.contentDetails", sizeof(fileSpec));
ret = GetFileInfo(dirSpec, fileSpec, &flags, &time);
if (!ret)
{
fh = open(strcat(dirSpec, fileSpec));
strlcat(dirSpec, fileSpec, sizeof(dirSpec));
fh = open(dirSpec);
fileSize = file_size(fh);
if (fileSize > 0 && fileSize < BVSTRLEN)
{
if (!error)
{
label[fileSize] = '\0';
strcpy(bvr->altlabel, label);
strlcpy(bvr->altlabel, label, sizeof(bvr->altlabel));
}
}
}
branches/cparm/i386/libsaio/fake_efi.c
604604
605605
606606
607
607
608608
609609
610610
611611
612
612
613613
614614
615615
static EFI_CHAR16* getSmbiosChar16(const char * key, size_t* len)
{
if (!GetgPlatformName() && strcmp(key, "SMproductname") == 0)
if (!GetgPlatformName() && strncmp(key, "SMproductname", sizeof("SMproductname")) == 0)
readSMBIOS(thePlatformName);
const char*PlatformName = GetgPlatformName() ;
const char*src = (strcmp(key, "SMproductname") == 0) ? PlatformName : getStringForKey(key, DEFAULT_SMBIOS_CONFIG);
const char*src = (strncmp(key, "SMproductname", sizeof("SMproductname")) == 0) ? PlatformName : getStringForKey(key, DEFAULT_SMBIOS_CONFIG);
EFI_CHAR16* dst = 0;
branches/cparm/i386/MakeInc.dir
2121
2222
2323
24
25
26
27
2428
2529
2630
OMIT_FRAME_POINTER_CFLAG=
HAVE_MD = YES
##CC = clang
##CC = llvm-gcc
##CC = gcc
installsrc:: $(SRCROOT)
cp $(ALLSRC) $(SRCROOT)
cd $(SRCROOT); chmod a-w $(ALLSRC)
branches/cparm/i386/boot2/boot.c
112112
113113
114114
115
116
117
118
119
120
121
122
123
124
125
126
115127
116128
117129
118130
119131
132
133
120134
121135
122136
......
242256
243257
244258
245
259
246260
247261
248262
......
618632
619633
620634
621
635
622636
623637
624638
......
10261040
10271041
10281042
1029
1043
10301044
10311045
10321046
static void zeroBSS(void)
{
#if (defined(__clang__)) /* WARNING : must be first, __GNUC__ seems to be also defined */
extern char bss_start __asm("section$start$__DATA$__bss");
extern char bss_end __asm("section$end$__DATA$__bss");
extern char common_start __asm("section$start$__DATA$__common");
extern char common_end __asm("section$end$__DATA$__common");
bzero(&bss_start, (&bss_end - &bss_start));
bzero(&common_start, (&common_end - &common_start));
#elif (defined(__GNUC__)) || (defined(__llvm__))
extern char _DATA__bss__begin, _DATA__bss__end;
extern char _DATA__common__begin, _DATA__common__end;
bzero(&_DATA__bss__begin, (&_DATA__bss__end - &_DATA__bss__begin));
bzero(&_DATA__common__begin, (&_DATA__common__end - &_DATA__common__begin));
#endif
}
//==========================================================================
{
wait = true;
if (strval && ((strcmp(strval, "no") == 0) || (strcmp(strval, "No") == 0)))
if (strval && ((strncmp(strval, "no", sizeof("no")) == 0) || (strncmp(strval, "No", sizeof("No")) == 0)))
{
wait = false;
}
long cachetime, kerneltime = 0, exttime;
if (trycache && !forcecache) do {
if (strcmp(bootInfo->bootFile, kDefaultKernel) != 0) {
if (strncmp(bootInfo->bootFile, kDefaultKernel,sizeof(kDefaultKernel)) != 0) {
// 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))
// Make sure this is a kext or mkext.
length = strlen(name);
if (strcmp(name + length - ext_size, ext)) continue;
if (strncmp(name + length - ext_size, ext, ext_size)) continue;
if (name_to_compare)
{
branches/cparm/i386/boot2/drivers.c
319319
320320
321321
322
322
323323
324324
325325
......
744744
745745
746746
747
747
748748
749749
750750
// Make sure this is a kext.
length = strlen(name);
if (strcmp(name + length - 5, ".kext")) continue;
if (strncmp(name + length - 5, ".kext", 5)) continue;
// Save the file name.
strlcpy(gFileName, name, DEFAULT_DRIVER_SPEC_SIZE);
required = XMLGetProperty(moduleDict, kPropOSBundleRequired);
if ( (required == 0) ||
(required->type != kTagTypeString) ||
!strcmp(required->string, "Safe Boot"))
!strncmp(required->string, "Safe Boot", sizeof("Safe Boot")))
{
XMLFreeTag(moduleDict);
return -2;
branches/cparm/i386/boot2/options.c
853853
854854
855855
856
856
857857
858858
859859
860860
861861
862
862
863863
864864
865865
866
866
867867
868868
869869
870
870
871871
872872
873873
874
874
875875
876876
877877
878878
879
879
880880
881881
882882
......
10631063
10641064
10651065
1066
1066
10671067
10681068
10691069
* TODO: this needs to be refactored.
*/
#if UNUSED
if (strcmp( booterCommand, "video" ) == 0)
if (strncmp( booterCommand, "video", sizeof("video") ) == 0)
{
printVBEModeInfo();
}
else
#endif
if ( strcmp( booterCommand, "memory" ) == 0)
if ( strncmp( booterCommand, "memory", sizeof("memory") ) == 0)
{
printMemoryInfo();
}
else if (strcmp(booterCommand, "lspci") == 0)
else if (strncmp(booterCommand, "lspci", sizeof( "lspci")) == 0)
{
lspci();
}
else if (strcmp(booterCommand, "more") == 0)
else if (strncmp(booterCommand, "more", sizeof("more")) == 0)
{
showTextFile(booterParam);
}
else if (strcmp(booterCommand, "rd") == 0)
else if (strncmp(booterCommand, "rd", sizeof("rd")) == 0)
{
if (execute_hook("processRAMDiskCommand", (void*)argPtr, &booterParam, NULL, NULL, NULL, NULL) != EFI_SUCCESS)
showMessage("ramdisk module not found, please install RamdiskLoader.dylib in /Extra/modules/");
}
else if (strcmp(booterCommand, "norescan") == 0)
else if (strncmp(booterCommand, "norescan", sizeof("norescan")) == 0)
{
if (get_env(envgEnableCDROMRescan))
{
} else {
if ( getValueForKey( kKernelNameKey, &val, &cnt, DEFAULT_BOOT_CONFIG ) ) {
strlcpy( bootInfo->bootFile, val, sizeof(bootInfo->bootFile) );
if (strcmp( bootInfo->bootFile, kDefaultKernel ) != 0) {
if (strncmp( bootInfo->bootFile, kDefaultKernel, sizeof(kDefaultKernel) ) != 0) {
safe_set_env(envgOverrideKernel,true);
}
} else if (((BVRef)(uint32_t)get_env(envgBootVolume))->kernelfound == true) {
branches/cparm/i386/modules/RamDiskLoader/ramdisk.c
308308
309309
310310
311
311
312312
313313
314314
315315
316
316
317317
318318
319319
320320
321
321
322322
323323
324324
325325
326
326
327327
328328
329329
330330
331
331
332332
333333
334334
char param[1024];
getNextArg(&ptr, param);
if (strcmp(cmd, "m") == 0)
if (strncmp(cmd, "m",sizeof("m")) == 0)
{
mountRAMDisk(param);
sleep(2);
}
else if (strcmp(cmd, "u") == 0)
else if (strncmp(cmd, "u", sizeof("u")) == 0)
{
umountRAMDisk();
sleep(2);
}
else if (strcmp(cmd, "e") == 0)
else if (strncmp(cmd, "e", sizeof("e")) == 0)
{
setRAMDiskBTHook(true);
sleep(2);
}
else if (strcmp(cmd, "d") == 0)
else if (strncmp(cmd, "d", sizeof("d")) == 0)
{
setRAMDiskBTHook(false);
sleep(2);
}
else if (strcmp(cmd, "i") == 0)
else if (strncmp(cmd, "i", sizeof("i")) == 0)
{
setActiveDisplayPage(1);
clearScreenRows(0, 24);
branches/cparm/i386/modules/KextPatcher/kext_patcher.c
377377
378378
379379
380
381
380
381
382382
383383
384384
#if UNUSED
if(/*patch_gma_deviceid &&*/
(
(strcmp(bundleID, "com.apple.driver.AppleIntelGMA950") == 0) ||
(strcmp(bundleID, "com.apple.driver.AppleIntelIntegratedFramebuffer") == 0)
(strncmp(bundleID, "com.apple.driver.AppleIntelGMA950", sizeof( "com.apple.driver.AppleIntelGMA950")) == 0) ||
(strncmp(bundleID, "com.apple.driver.AppleIntelIntegratedFramebuffer",sizeof("com.apple.driver.AppleIntelIntegratedFramebuffer")) == 0)
)
)
{
branches/cparm/i386/modules/GUI/gui.c
427427
428428
429429
430
430
431431
432432
433433
......
444444
445445
446446
447
447
448448
449449
450450
......
503503
504504
505505
506
506
507507
508508
509509
......
847847
848848
849849
850
850
851851
852852
853853
......
11811181
11821182
11831183
1184
1184
11851185
11861186
11871187
11881188
1189
1189
11901190
11911191
11921192
11931193
1194
1194
11951195
11961196
11971197
......
12051205
12061206
12071207
1208
1208
12091209
12101210
12111211
12121212
1213
1213
12141214
12151215
12161216
12171217
1218
1218
12191219
12201220
12211221
......
12651265
12661266
12671267
1268
1268
12691269
12701270
12711271
......
12871287
12881288
12891289
1290
1290
12911291
12921292
12931293
......
25822582
25832583
25842584
2585
2585
25862586
25872587
25882588
int i;
for (i = 0; (unsigned)i < sizeof(images) / sizeof(images[0]); i++)
{
if (strcmp(name, images[i].name) == 0)
if (strncmp(name, images[i].name, sizeof(images[i].name)) == 0)
return i; // found the name
}
return -1;
// NOTE: This algorithm assumes that the embeddedImages is sorted.
// This is currently done using the make file. If the array is every
// manualy generated, this *will* fail to work properly.
while((result = strcmp(name, embeddedImages[compareIndex].name)) != 0)
while((result = strncmp(name, embeddedImages[compareIndex].name, sizeof(embeddedImages[compareIndex].name))) != 0)
{
if(result > 0)// We need to search a HIGHER index
{
return 1;
}
}
sprintf(dirspec, "%s/%s/%s.png", src, theme_name, image);
snprintf(dirspec, sizeof(dirspec),"%s/%s/%s.png", src, theme_name, image);
width = 0;
height = 0;
// check layout for horizontal or vertical
gui.layout = HorizontalLayout;
if(getValueForKey( "devices_layout", &string, &len, theme)) {
if (!strcmp (string, "vertical")) {
if (!strncmp (string, "vertical",sizeof("vertical"))) {
gui.layout = VerticalLayout;
}
}
retry:
ret = GetFileInfo("rd(0,0)/Extra/", "Themes", &flags, &time);
if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
sprintf(dirsrc, "rd(0,0)/Extra/Themes");
snprintf(dirsrc,sizeof(dirsrc), "rd(0,0)/Extra/Themes");
} else {
ret = GetFileInfo("/Extra/", "Themes", &flags, &time);
if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
sprintf(dirsrc, "/Extra/Themes");
snprintf(dirsrc,sizeof(dirsrc), "/Extra/Themes");
} else {
ret = GetFileInfo("bt(0,0)/Extra/", "Themes", &flags, &time);
if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
sprintf(dirsrc, "bt(0,0)/Extra/Themes");
snprintf(dirsrc,sizeof(dirsrc), "bt(0,0)/Extra/Themes");
} else {
printf("Failed to find the /extra/Themes folder\n");
{
ret = GetFileInfo("rd(0,0)/Extra/Themes/", theme_name, &flags, &time);
if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
sprintf(dirsrc, "rd(0,0)/Extra/Themes");
snprintf(dirsrc,sizeof(dirsrc), "rd(0,0)/Extra/Themes");
} else {
ret = GetFileInfo("/Extra/Themes/", theme_name, &flags, &time);
if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
sprintf(dirsrc, "/Extra/Themes");
snprintf(dirsrc,sizeof(dirsrc), "/Extra/Themes");
} else {
ret = GetFileInfo("bt(0,0)/Extra/Themes/", theme_name, &flags, &time);
if ((ret == 0) && ((flags & kFileTypeMask) == kFileTypeDirectory)) {
sprintf(dirsrc, "bt(0,0)/Extra/Themes");
snprintf(dirsrc,sizeof(dirsrc), "bt(0,0)/Extra/Themes");
} else {
printf("Failed to find the /extra/Themes/%s folder\n",theme_name);
}
#endif
if (ret && (strcmp(theme_name, THEME_NAME_DEFAULT) != 0)) {
if (ret && (strncmp(theme_name, THEME_NAME_DEFAULT,sizeof(THEME_NAME_DEFAULT)) != 0)) {
theme_name = THEME_NAME_DEFAULT;
ret = startGUI();
return 1;
}
sprintf(dirspec, "%s/%s/theme.plist", dirsrc ,theme_name);
snprintf(dirspec, sizeof(dirspec), "%s/%s/theme.plist", dirsrc ,theme_name);
if (loadConfigFile(dirspec, &themeConfig) != 0) {
usePngImage = false;
return;
}
sprintf(dirspec, "%s/%s/boot.png", src, theme_name);
snprintf(dirspec, sizeof(dirspec), "%s/%s/boot.png", src, theme_name);
if ((strlen(theme_name) == 0) || (loadPngImage(dirspec, &bootImageWidth, &bootImageHeight, &bootImageData) == -1)) {
#ifdef EMBED_THEME
if ((loadEmbeddedPngImage(__boot_png, __boot_png_len, &bootImageWidth, &bootImageHeight, &bootImageData)) == -1)
branches/cparm/i386/modules/GUI/GUI_module.c
810810
811811
812812
813
813
814
814815
815816
816817
......
830831
831832
832833
833
834
834835
835836
836837
......
10381039
10391040
10401041
1041
1042
10421043
10431044
10441045
......
10491050
10501051
10511052
1052
1053
10531054
10541055
10551056
......
10601061
10611062
10621063
1063
1064
10641065
10651066
10661067
1067
1068
10681069
10691070
10701071
1071
1072
10721073
10731074
10741075
10751076
1076
1077
10771078
10781079
10791080
char *name = NULL;
int cnt;
if (getValueForKey(kCDROMPromptKey, &val, &cnt, DEFAULT_BOOT_CONFIG)) {
if (getValueForKey(kCDROMPromptKey, &val, &cnt, DEFAULT_BOOT_CONFIG))
{
prompt = malloc(cnt + 1);
if (!prompt) {
stop("Couldn't allocate memory for the prompt\n"); //TODO: Find a better stategie
stop("Couldn't allocate memory for the prompt\n"); //TODO: Find a better stategie
return -1;
}
sprintf(prompt, "Press ENTER to start up from %s, or press any key to enter startup options.", name);
snprintf(prompt, 256 ,"Press ENTER to start up from %s, or press any key to enter startup options.", name);
free(name);
}
/*
* TODO: this needs to be refactored.
*/
if (strcmp( booterCommand, "video" ) == 0)
if (strncmp( booterCommand, "video", sizeof("video") ) == 0)
{
if (getVideoMode() == GRAPHICS_MODE)
{
printVBEModeInfo();
}
}
else if ( strcmp( booterCommand, "memory" ) == 0)
else if ( strncmp( booterCommand, "memory", sizeof("memory") ) == 0)
{
if (getVideoMode() == GRAPHICS_MODE )
{
printMemoryInfo();
}
}
else if (strcmp(booterCommand, "lspci") == 0)
else if (strncmp(booterCommand, "lspci", sizeof( "lspci")) == 0)
{
lspci();
}
else if (strcmp(booterCommand, "more") == 0)
else if (strncmp(booterCommand, "more", sizeof("more")) == 0)
{
showTextFile(booterParam);
}
else if (strcmp(booterCommand, "rd") == 0)
else if (strncmp(booterCommand, "rd", sizeof("rd")) == 0)
{
if (execute_hook("processRAMDiskCommand", (void*)argPtr, &booterParam, NULL, NULL, NULL, NULL) != EFI_SUCCESS)
showMessage("ramdisk module not found, please install RamdiskLoader.dylib in /Extra/modules/");
}
else if (strcmp(booterCommand, "norescan") == 0)
else if (strncmp(booterCommand, "norescan", sizeof("norescan")) == 0)
{
if (get_env(envgEnableCDROMRescan))
{
branches/cparm/i386/modules/GraphicsEnabler/gma.c
128128
129129
130130
131
132
131
132
133133
134134
135135
136136
137137
138
139
138
139
140140
141141
142142
143143
144144
145
145
146146
147147
148148
......
168168
169169
170170
171
171
172172
173173
174174
devprop_add_value(device, "model", (uint8_t*)model, (strlen(model) + 1));
devprop_add_value(device, "device_type", (uint8_t*)"display", 8);
if ((strcmp(model, "Mobile GMA950") == 0) ||
(strcmp(model, "Mobile GMA3150") == 0))
if ((strncmp(model, "Mobile GMA950", sizeof("Mobile GMA950")) == 0) ||
(strncmp(model, "Mobile GMA3150", sizeof("Mobile GMA3150")) == 0))
{
devprop_add_value(device, "AAPL,HasPanel", reg_TRUE, 4);
devprop_add_value(device, "built-in", &BuiltIn, 1);
devprop_add_value(device, "class-code", ClassFix, 4);
}
else if ((strcmp(model, "Desktop GMA950")== 0) ||
(strcmp(model, "Desktop GMA3150") == 0))
else if ((strncmp(model, "Desktop GMA950",sizeof("Desktop GMA950"))== 0) ||
(strncmp(model, "Desktop GMA3150",sizeof("Desktop GMA3150")) == 0))
{
BuiltIn = 0x01;
devprop_add_value(device, "built-in", &BuiltIn, 1);
devprop_add_value(device, "class-code", ClassFix, 4);
}
else if ( strcmp(model, "GMAX3100") == 0 )
else if ( strncmp(model, "GMAX3100", sizeof("GMAX3100")) == 0 )
{
devprop_add_value(device, "AAPL,HasPanel",GMAX3100_vals[0], 4);
devprop_add_value(device, "AAPL,SelfRefreshSupported",GMAX3100_vals[1], 4);
devprop_add_value(device, "AAPL01,Stretch",GMAX3100_vals[21], 4);
devprop_add_value(device, "class-code", ClassFix, 4);
}
else if (strcmp(model, "Intel HD Graphics 3000") == 0)
else if (strncmp(model, "Intel HD Graphics 3000", sizeof("Intel HD Graphics 3000")) == 0)
{
devprop_add_value(device, "AAPL,os-info", HD3000_os_info, 20);
}
branches/cparm/i386/modules/GraphicsEnabler/nvidia.c
10441044
10451045
10461046
1047
1047
10481048
10491049
10501050
strncpy(sig, (char *)&dcbtable[-7], 7);
recordlength = 10;
if (strcmp(sig, "DEV_REC")) {
if (strncmp(sig, "DEV_REC",sizeof("DEV_REC"))) {
printf("Bad Display Configuration Block signature (%s)\n", sig);
return PATCH_ROM_FAILED;
}
branches/cparm/i386/modules/SMBiosGetters/mysmbios.c
739739
740740
741741
742
742
743743
744744
745745
746
746
747747
748748
749749
......
919919
920920
921921
922
922
923923
924924
925925
{
sm_chosen = sm_macbook_defaults ;
}
else if (!strcmp ("iMac12,1", str))
else if (!strncmp ("iMac12,1", str,sizeof("iMac12,1")))
{
sm_chosen = sm_imac_sandy_defaults ;
}
else if (!strcmp ("iMac11,1", str))
else if (!strncmp ("iMac11,1", str, sizeof("iMac11,1")))
{
sm_chosen = sm_imac_core_defaults ;
}
if (SMBSetters[idx].keyString)
{
if ((SMBSetters[idx].defaultValue) && *(SMBSetters[idx].defaultValue) && randomSerial && (!strcmp ("SMserial", SMBSetters[idx].keyString)))
if ((SMBSetters[idx].defaultValue) && *(SMBSetters[idx].defaultValue) && randomSerial && (!strncmp ("SMserial", SMBSetters[idx].keyString, sizeof("SMserial"))))
{
string = *(SMBSetters[idx].defaultValue);
break;
branches/cparm/i386/modules/Keymapper/Keylayout.c
145145
146146
147147
148
148
149149
150150
151151
{
snprintf(layoutPath, sizeof(layoutPath),"/Extra/Keymaps/%s", val);
// Add the extension if needed
if (len <= 4 || strcmp(val+len-4,".lyt") != 0)
if (len <= 4 || strncmp(val+len-4,".lyt", sizeof(".lyt")) != 0)
strlcat(layoutPath, ".lyt", sizeof(layoutPath));
if (!load_keyboard_layout_file(layoutPath))
branches/cparm/i386/modules/Keymapper/Keymapper.c
230230
231231
232232
233
233
234234
235235
236236
map_kb_type = "NONE"; // Default to QWERTY
}
if (map_kb_type && (strcmp(map_kb_type, "AZERTY") == 0))
if (map_kb_type && (strncmp(map_kb_type, "AZERTY",sizeof("AZERTY")) == 0))
c = AZERTY_switch(c);
out:
branches/cparm/i386/modules/SMBiosPatcher/smbios_patcher.c
505505
506506
507507
508
508
509509
510510
511511
512
512
513513
514514
515515
......
535535
536536
537537
538
538
539539
540540
541541
......
970970
971971
972972
973
973
974974
975975
976976
......
10221022
10231023
10241024
1025
1025
10261026
10271027
10281028
......
11391139
11401140
11411141
1142
1142
11431143
11441144
11451145
......
12651265
12661266
12671267
1268
1268
12691269
12701270
12711271
{
sm_chosen = sm_macbook_defaults ;
}
else if (!strcmp ("iMac12,1", str))
else if (!strncmp ("iMac12,1", str, sizeof("iMac12,1")))
{
sm_chosen = sm_imac_sandy_defaults ;
}
else if (!strcmp ("iMac11,1", str))
else if (!strncmp ("iMac11,1", str,sizeof("iMac11,1")))
{
sm_chosen = sm_imac_core_defaults ;
}
}
if (!strcmp ("SMserial", key)) {
if (!strncmp ("SMserial", key, sizeof("SMserial"))) {
if (!serial_done) {
bzero (fake_serial,sizeof(fake_serial));
snprintf(altname, sizeof(altname),"%s_%d",smbios_properties[j].name, tablespresent[cur->type] + 1);
if (smbios_properties[j].table_type == cur->type &&
smbios_properties[j].value_type == SMSTRING &&
smbios_properties[j].auto_str && randomSerial && (!strcmp ("SMserial", smbios_properties[j].name))) {
smbios_properties[j].auto_str && randomSerial && (!strncmp ("SMserial", smbios_properties[j].name, sizeof("SMserial")))) {
stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[cur->type])) + 1;
snprintf(altname, sizeof(altname), "%s_%d",smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type] + 1);
if (smbios_properties[j].table_type == smbios_table_descriptions[i].type &&
smbios_properties[j].value_type==SMSTRING &&
smbios_properties[j].auto_str && randomSerial && (!strcmp ("SMserial", smbios_properties[j].name))) {
smbios_properties[j].auto_str && randomSerial && (!strncmp ("SMserial", smbios_properties[j].name, sizeof("SMserial")))) {
stringlen += strlen(smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[smbios_table_descriptions[i].type])) + 1;
if (smbios_properties[j].table_type == newcur->type) {
switch (smbios_properties[j].value_type) {
case SMSTRING:
if (smbios_properties[j].auto_str && randomSerial && (!strcmp ("SMserial", smbios_properties[j].name)))
if (smbios_properties[j].auto_str && randomSerial && (!strncmp ("SMserial", smbios_properties[j].name,sizeof("SMserial"))))
{
str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
size = strlen(str);
if (smbios_properties[j].table_type == newcur->type) {
switch (smbios_properties[j].value_type) {
case SMSTRING:
if (smbios_properties[j].auto_str && randomSerial && (!strcmp ("SMserial", smbios_properties[j].name)))
if (smbios_properties[j].auto_str && randomSerial && (!strncmp ("SMserial", smbios_properties[j].name,sizeof("SMserial"))))
{
str = smbios_properties[j].auto_str(smbios_properties[j].name, tablespresent[newcur->type]);
size = strlen(str);
branches/cparm/i386/modules/Resolution/915resolution.c
287287
288288
289289
290
290
291291
292292
293293
*/
map->ati_tables.base = map->bios_ptr;
map->ati_tables.AtomRomHeader = (ATOM_ROM_HEADER *) (map->bios_ptr + *(unsigned short *) (map->bios_ptr + OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER));
if (strcmp ((char *) map->ati_tables.AtomRomHeader->uaFirmWareSignature, "ATOM") == 0)
if (strncmp ((char *) map->ati_tables.AtomRomHeader->uaFirmWareSignature, "ATOM", sizeof("ATOM")) == 0)
{
// ATI Radeon Card
map->bios = BT_ATI_1;
branches/cparm/i386/modules/ACPICodec/acpi_codec.c
182182
183183
184184
185
185
186186
187187
188188
......
16011601
16021602
16031603
1604
1604
16051605
16061606
16071607
......
44204420
44214421
44224422
4423
4423
44244424
44254425
44264426
......
45984598
45994599
46004600
4601
4601
46024602
46034603
46044604
......
48014801
48024802
48034803
4804
4804
48054805
48064806
48074807
resolve_##s(unsigned u defaultentry, char *str, int base) \
{\
unsigned u entry = defaultentry;\
if (str && (strcmp(str,"Default") != 0)) {\
if (str && (strncmp(str,"Default",sizeof("Default")) != 0)) {\
entry = strtoul((const char *)str, NULL,base);\
}\
return entry;\
{
char *tmpstr = XMLCastString(XMLGetProperty(PstateTag, (const char*)"Mode"));
if (strcmp(tmpstr,"Expert") == 0)
if (strncmp(tmpstr,"Expert",sizeof("Expert")) == 0)
{
p_states_count = pstate_tag_count - 1 ; // - 1 = - ("Mode" tag)
expert = 1;
if ( match_drop )
{
char *tmp = XMLCastString(match_drop);
if (tmp && (strcmp(tmp,"No") != 0))
if (tmp && (strncmp(tmp,"No",sizeof("No")) != 0))
{
dropoffset++;
DBG(" %s table dropped\n",tableSig);
if ( match_drop )
{
char *tmp = XMLCastString(match_drop);
if (strcmp(tmp,"No") != 0)
if (strncmp(tmp,"No",sizeof("No")) != 0)
{
dropoffset++;
DBG(" %s table dropped\n",tableSig);
// Make sure this is a kext.
length = strlen(name);
if (strcmp(name + length - 4, ".aml"))
if (strncmp(name + length - 4, ".aml",sizeof(".aml")) != 0)
{
#if DEBUG_ACPI
printf("Ignoring %s\n", name);
branches/cparm/i386/libsa/bzero.s
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
/*
* Copyright (c) 2000 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@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
#include <architecture/i386/asm_help.h>
/*
* void *memset(void * addr, int pattern, size_t length)
*/
LABEL(_memset)
pushl%edi
movl4+ 4(%esp),%edi/* addr */
movb4+ 8(%esp),%al/* pattern */
movl4+ 12(%esp),%edx/* length */
movb%al,%ah
movw%ax,%cx
shll$16,%eax
movw%cx,%ax
cld
/* zero longs */
movl%edx,%ecx
shrl$2,%ecx
rep
stosl
/* zero bytes */
movl%edx,%ecx
andl$3,%ecx
rep
stosb
movl4+ 4(%esp),%eax/* returns its first argument */
popl%edi
ret
/*
* void bzero(char * addr, size_t length)
*/
LABEL(___bzero) /* only for a compatibility issue */
LABEL(_bzero)
pushl%edi
movl4+ 4(%esp),%edi/* addr */
movl4+ 8(%esp),%edx/* length */
xorl%eax,%eax
cld
/* zero longs */
movl%edx,%ecx
shrl$2,%ecx
rep
stosl
/* zero bytes */
movl%edx,%ecx
andl$3,%ecx
rep
stosb
popl%edi
ret
branches/cparm/i386/libsa/bcopy.s
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
/*
* Copyright (c) 2000 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@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
#include <architecture/i386/asm_help.h>
/* void *memcpy((void *) to, (const void *) from, (size_t) bcount) */
LABEL(_memcpy)
pushl%edi
pushl%esi
movl8+ 4(%esp),%edi/* to */
movl%edi,%eax/* returns its first argument */
movl8+ 8(%esp),%esi/* from */
memcpy_common:
movl8+ 12(%esp),%edx/* number of bytes */
cld
/* move longs*/
movl%edx,%ecx
shrl$2,%ecx
rep
movsl
/* move bytes*/
movl%edx,%ecx
andl$3,%ecx
rep
movsb
popl%esi
popl%edi
ret
/* void bcopy((const char *) from, (char *) to, (unsigned int) count) */
LABEL(_bcopy_no_overwrite)
pushl%edi
pushl%esi
movl8+ 8(%esp),%edi/* to */
movl8+ 4(%esp),%esi/* from */
jmpmemcpy_common
/* bcopy16(from, to, bcount) using word moves */
LABEL(_bcopy16)
pushl%edi
pushl%esi
movl8+12(%esp),%edx/* 8 for the two pushes above */
movl8+ 8(%esp),%edi
movl8+ 4(%esp),%esi
/* move words */
0:cld
movl%edx,%ecx
shrl$1,%ecx
rep
movsw
/* move bytes */
movl%edx,%ecx
andl$1,%ecx
rep
movsb
popl%esi
popl%edi
ret
/*
* Based on NetBSD's bcopy.S from their libc.
* bcopy(src, dst, cnt)
* ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
*/
LABEL(_bcopy)
pushl %esi
pushl %edi
movl 12(%esp),%esi
movl 16(%esp),%edi
movl 20(%esp),%ecx
movl %edi,%edx
subl %esi,%edx
cmpl %ecx,%edx /* overlapping && src < dst? */
movl %ecx,%edx
jb 1f
shrl $2,%ecx /* copy by 32-bit words */
cld /* nope, copy forwards */
rep
movsl
movl %edx,%ecx
andl $3,%ecx /* any bytes left? */
rep
movsb
popl %edi
popl %esi
ret
1:
addl %ecx,%edi /* copy backwards */
addl %ecx,%esi
decl %edi
decl %esi
andl $3,%ecx /* any fractional bytes? */
std
rep
movsb
movl %edx,%ecx /* copy remainder by 32-bit words */
shrl $2,%ecx
subl $3,%esi
subl $3,%edi
rep
movsl
popl %edi
popl %esi
cld
ret
branches/cparm/i386/libsa/memcmp.s
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
/*
* Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_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. 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_LICENSE_HEADER_END@
*/
// *************** ***********
// * M E M C M P * and * B C M P *
// *************** ***********
//
// intmemcmp(const char *s1, const char *s2, size_t len);
// int bcmp(const char *s1, const char *s2, size_t len);
//
// Bcmp returns (+,0,-), whereas memcmp returns the true difference
// between the first differing bytes, but we treat them identically.
//
// We optimize the compare by doing it with SSE. This introduces
// a complication: if we blindly did vector loads from both sides until
// finding a difference, we might get a spurious page fault by
// reading bytes past the difference. To avoid this, we never do a load
// that crosses a page boundary.
#definekShort18// too short for vectors (must be >16)
.text
.align 4
.globl _memcmp
.globl _bcmp
_memcmp:// int memcmp(const char *s1,const char *s2,size_t len);
_bcmp:// int bcmp(const char *s1,const char *s2,size_t len);
pushl%esi
pushl%edi
movl20(%esp),%ecx// get length
movl12(%esp),%esi// get LHS ptr
movl16(%esp),%edi// get RHS ptr
cmpl$(kShort),%ecx// worth accelerating?
jaLNotShort// yes
// Too short to bother with parallel compares. Loop over bytes.
//%esi = LHS ptr
//%edi = RHS ptr
//%ecx = length (<= kShort)
LShort:
testl%ecx,%ecx// 0-length?
jnzLShortLoop// no
xorl%eax,%eax// return 0
jmpLExit
.align4,0x90// align inner loops to optimize I-fetch
LShortLoop:// loop over bytes
movzb(%esi),%eax// get LHS byte
movzb(%edi),%edx// get RHS byte
incl%esi
incl%edi
subl%edx,%eax// compare them
jnzLExit// done if not equal
decl%ecx// decrement length
jnzLShortLoop
LExit:// return value is in %eax
popl%edi
popl%esi
ret
LNotEqual:// here from LLoopOverBytes with LHS in eax
movzb(%edi),%edx// get RHS byte
subl%edx,%eax// generate return value (nonzero)
popl%edi
popl%esi
ret
// Loop over bytes until we reach end of a page.
//%esi = LHS ptr
//%edi = RHS ptr
//%ecx = length remaining after end of loop (ie, already adjusted)
//%edx = #bytes until next page (1..15)
.align4,0x90// align inner loops to optimize I-fetch
LLoopOverBytes:
movzb(%esi),%eax// get LHS byte
inc%esi
cmpb(%edi),%al// compare to RHS byte
jnzLNotEqual// done if not equal
inc%edi
dec%edx// more to go?
jnzLLoopOverBytes
// Long enough to justify overhead of setting up vector compares. In order to
// avoid spurious page faults, we loop over:
//
//min( length, bytes_in_LHS_page, bytes_in_RHS_page) >> 4
//
// 16-byte chunks. When we near a page end, we have to revert to a byte-by-byte
// comparison until reaching the next page, then resume the vector comparison.
//%esi = LHS ptr
//%edi = RHS ptr
//%ecx = length (> kShort)
LNotShort:
movl%esi,%eax// copy ptrs
movl%edi,%edx
andl$4095,%eax// mask down to page offsets
andl$4095,%edx
cmpl%eax,%edx// which is bigger?
cmova%edx,%eax// %eax = max(LHS offset, RHS offset);
movl$4096,%edx
subl%eax,%edx// get #bytes to next page crossing
cmpl%ecx,%edx// will operand run out first?
cmova%ecx,%edx// get min(length remaining, bytes to page end)
movl%edx,%eax
shrl$4,%edx// get #chunks till end of operand or page
jnzLLoopOverChunks// enter vector loop
// Too near page end for vectors.
subl%eax,%ecx// adjust length remaining
movl%eax,%edx// %edx <- #bytes to page end
cmpl$(kShort),%ecx// will there be enough after we cross page for vectors?
jaLLoopOverBytes// yes
addl%eax,%ecx// no, restore total length remaining
jmpLShortLoop// compare rest byte-by-byte (%ecx != 0)
// Loop over 16-byte chunks.
//%esi = LHS ptr
//%edi = RHS ptr
//%ecx = length remaining
//%edx = chunk count
.align4,0x90// align inner loops to optimize I-fetch
LLoopOverChunks:
movdqu(%esi),%xmm0// get LHS
movdqu(%edi),%xmm1// get RHS
addl$16,%esi
pcmpeqb%xmm1,%xmm0// compare LHS to RHS
addl$16,%edi
pmovmskb %xmm0,%eax// collect comparison result bits (1 if equal)
subl$16,%ecx// adjust length remaining
xorl$0xFFFF,%eax// all equal?
jneLDifferent// no, we found differing bytes
dec%edx// more to go?
jnzLLoopOverChunks
cmpl$(kShort),%ecx// a lot more to compare?
jbeLShort// no
jmpLNotShort// compute distance to next page crossing etc
// Found a difference.
//%esi = LHS ptr, already advanced by 16
//%edi = RHS ptr, already advanced by 16
//%eax = complemented compare vector (ie, 0 == equal)
LDifferent:
bsf%eax,%edx// which byte differed?
subl$16,%esi// point to byte 0 while we wait for bit scan
subl$16,%edi
movzb(%esi,%edx),%eax// get LHS byte
movzb(%edi,%edx),%ecx// get RHS byte
subl%ecx,%eax// compute difference (ie, return value)
popl%edi
popl%esi
ret
branches/cparm/i386/libsa/__bzero.s
1
2
3
.globl ___bzero
___bzero:
jmp _bzero
branches/cparm/i386/libsa/memset_pattern_sse2.s
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
/*
* Copyright (c) 2005-2006 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@
*/
/* The common path for nonzero memset and the memset_pattern routines,
* tuned for Pentium-M class processors with SSE2 and 64-byte cache lines.
* This is used by the following functions:
*
*void *memset(void *b, int c, size_t len); // when c!=0
*void memset_pattern4(void *b, const void *c4, size_t len);
*void memset_pattern8(void *b, const void *c8, size_t len);
*void memset_pattern16(void *b, const void *c16, size_t len);
*
* Note bzero() and memset() of 0 are handled separately.
*/
#definekShort63
#definekVeryLong(1024*1024)
// Initial entry from Libc with parameters passed in registers. Although we
// correctly handle misaligned ptrs and short operands, they are inefficient.
// Therefore our caller should filter out short operands and exploit local
// knowledge (ie, original pattern length) to align the ptr if possible.
// When called, we expect:
//%edi = ptr to memory to set (not necessarily aligned)
//%edx = length (may be short or even 0)
//%xmm0 = the pattern to store
// Return conditions:
//%eax, %edi, %esi, %ecx, and %edx all trashed
.align 5
.private_extern _memset_pattern
_memset_pattern:
cmpl $(kShort),%edx// long enough to bother aligning?
jaLNotShort// yes
jmpLShort// no
// Here for short operands or the end of long ones.
// %edx = length
// %edi = ptr (may not be not aligned)
// %xmm0 = pattern
LUnalignedStore16:
movdqu%xmm0,(%edi)// stuff in another 16 bytes
subl$16,%edx
addl$16,%edi
LShort:
cmpl$16,%edx// room for another vector?
jgeLUnalignedStore16// yes
LLessThan16:// here at end of copy with < 16 bytes remaining
test$8,%dl// 8-byte store required?
jz2f// no
movq%xmm0,(%edi)// pack in 8 low bytes
psrldq$8,%xmm0// then shift vector down 8 bytes
addl$8,%edi
2:
test$4,%dl// 4-byte store required?
jz3f// no
movd%xmm0,(%edi)// pack in 4 low bytes
psrldq$4,%xmm0// then shift vector down 4 bytes
addl$4,%edi
3:
andl$3,%edx// more to go?
jz5f// no
movd%xmm0,%eax// move remainders out into %eax
4:// loop on up to three bytes
movb%al,(%edi)// pack in next byte
shrl$8,%eax// shift next byte into position
inc%edi
dec%edx
jnz4b
5:ret
// Long enough to justify aligning ptr. Note that we have to rotate the
// pattern to account for any alignment. We do this by doing two unaligned
// stores, and then an aligned load from the middle of the two stores.
// This will stall on store forwarding alignment mismatch, and the unaligned
// stores can be pretty slow too, but the alternatives aren't any better.
// Fortunately, in most cases our caller has already aligned the ptr.
// %edx = length (> kShort)
// %edi = ptr (may not be aligned)
// %xmm0 = pattern
LNotShort:
movl %edi,%ecx// copy dest ptr
negl %ecx
andl $15,%ecx // mask down to #bytes to 16-byte align
jzLAligned// skip if already aligned
movdqu%xmm0,(%edi)// store 16 unaligned bytes
movdqu%xmm0,16(%edi)// and 16 more, to be sure we have an aligned chunk
addl%ecx,%edi// now point to the aligned chunk
subl%ecx,%edx// adjust remaining count
movdqa(%edi),%xmm0// get the rotated pattern (probably stalling)
addl$16,%edi// skip past the aligned chunk
subl$16,%edx
// Set up for 64-byte loops.
// %edx = length remaining
// %edi = ptr (aligned)
// %xmm0 = rotated pattern
LAligned:
movl%edx,%ecx// copy length remaining
andl $63,%edx // mask down to residual length (0..63)
andl $-64,%ecx // %ecx <- #bytes we will zero in by-64 loop
jzLNoMoreChunks// no 64-byte chunks
addl %ecx,%edi // increment ptr by length to move
cmpl$(kVeryLong),%ecx// long enough to justify non-temporal stores?
jgeLVeryLong// yes
negl %ecx// negate length to move
jmp1f
// Loop over 64-byte chunks, storing into cache.
.align4,0x90// keep inner loops 16-byte aligned
1:
movdqa %xmm0,(%edi,%ecx)
movdqa %xmm0,16(%edi,%ecx)
movdqa %xmm0,32(%edi,%ecx)
movdqa %xmm0,48(%edi,%ecx)
addl $64,%ecx
jne 1b
jmpLNoMoreChunks
// Very long operands: use non-temporal stores to bypass cache.
LVeryLong:
negl %ecx// negate length to move
jmp1f
.align4,0x90// keep inner loops 16-byte aligned
1:
movntdq %xmm0,(%edi,%ecx)
movntdq %xmm0,16(%edi,%ecx)
movntdq %xmm0,32(%edi,%ecx)
movntdq %xmm0,48(%edi,%ecx)
addl $64,%ecx
jne 1b
sfence // required by non-temporal stores
jmpLNoMoreChunks
// Handle leftovers: loop by 16.
// %edx = length remaining (<64)
// %edi = ptr (aligned)
// %xmm0 = rotated pattern
LLoopBy16:
movdqa%xmm0,(%edi)// pack in 16 more bytes
subl$16,%edx// decrement count
addl$16,%edi// increment ptr
LNoMoreChunks:
cmpl$16,%edx// more to go?
jgeLLoopBy16// yes
jmpLLessThan16// handle up to 15 remaining bytes
branches/cparm/i386/libsa/strcpy.s
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
/*
* Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_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. 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_LICENSE_HEADER_END@
*/
// ***************
// * S T R C P Y *
// ***************
//
// char *strcpy(const char *dst, const char *src);
//
// We optimize the move by doing it vector parallel. This introduces
// a complication: if we blindly did vector load/stores until finding
// a 0, we might get a spurious page fault by touching bytes past it.
// To avoid this, we never do a load that crosses a page boundary,
// and never store a byte we don't have to.
//
// We align the destination, because unaligned vector stores are slow.
.text
.globl _strcpy
.align 4
_strcpy:// char *strcpy(const char *dst, const char *src);
pushl%edi
movl8(%esp),%edi// get dest ptr
movl12(%esp),%ecx// get source ptr
movl%edi,%edx// copy dest ptr
negl%edx
andl$15,%edx// how many bytes to align dest ptr?
jnzLLoopOverBytes// not aligned, so go do so
// In order to avoid spurious page faults, we loop until nearing the source page
// end. Then we revert to a byte-by-byte loop for 16 bytes until the page is crossed,
// then resume the vector loop.
//%ecx = source ptr (unaligned)
//%edi = dest ptr (aligned)
LNextChunk:
movl%ecx,%eax// copy source ptr
movl$4096,%edx
andl$4095,%eax// get offset into source page
subl%eax,%edx// get #bytes remaining in source page
shrl$4,%edx// get #chunks till end of page
jnzLLoopOverChunks// enter vector loop
movl$16,%edx// move 16 bytes to cross page but keep dest aligned
jmpLLoopOverBytes
// Loop over bytes.
//%ecx = source ptr
//%edi = dest ptr
//%edx = byte count
.align4,0x90// align inner loops to optimize I-fetch
LLoopOverBytes:
movzb(%ecx),%eax// get source byte
inc%ecx
movb%al,(%edi)// pack into dest
inc%edi
testl%eax,%eax// 0?
jzLDone// yes, we're done
dec%edx// more to go?
jnzLLoopOverBytes
jmpLNextChunk// we've come to end of page
// Loop over 16-byte chunks.
//%ecx = source ptr (unaligned)
//%edi = dest ptr (aligned)
//%edx = chunk count
.align4,0x90// align inner loops to optimize I-fetch
LLoopOverChunks:
movdqu(%ecx),%xmm1// get source
pxor%xmm0,%xmm0// get some 0s
addl$16,%ecx
pcmpeqb%xmm1,%xmm0// compare source to 0s
pmovmskb %xmm0,%eax// get result mask for 0 check
testl%eax,%eax// any 0s?
jnzLFound0// yes, exit loop
movdqa%xmm1,(%edi)// no 0s so do aligned store into destination
addl$16,%edi
dec%edx// more to go?
jnzLLoopOverChunks
movl$16,%edx// move 16 bytes
jmpLLoopOverBytes// cross page but keep dest aligned
// Found a zero in the vector. Figure out where it is, and store the bytes
// up to it.
//%edi = dest ptr (aligned)
//%eax = result mask
//%xmm1 = source vector
LFound0:
bsf%eax,%edx// find first 0
inc%edx// we need to store the 0 too
test$16,%dl// was 0 last byte?
jz8f// no
movdqa%xmm1,(%edi)// yes, store entire vector
jmpLDone
8:
test$8,%dl// 8-byte store required?
jz4f// no
movq%xmm1,(%edi)// pack in 8 low bytes
psrldq$8,%xmm1// then shift vector down 8 bytes
addl$8,%edi
4:
test$4,%dl// 4-byte store required?
jz3f// no
movd%xmm1,(%edi)// pack in 4 low bytes
psrldq$4,%xmm1// then shift vector down 4 bytes
addl$4,%edi
3:
andl$3,%edx// more to go?
jzLDone// no
movd%xmm1,%eax// move remainders out of vector into %eax
1:// loop on up to three bytes
movb%al,(%edi)// pack in next byte
shrl$8,%eax// shift next byte into position
inc%edi
dec%edx
jnz1b
LDone:
movl8(%esp),%eax// original dest ptr is return value
popl%edi
ret
branches/cparm/i386/libsa/strncmp.s
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
/*
* Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_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. 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_LICENSE_HEADER_END@
*/
// *****************
// * S T R N C M P *
// *****************
//
// intstrncmp(const char *s1, const char *s2, size_t len);
//
// We optimize the compare by doing it vector parallel. This introduces
// a complication: if we blindly did vector loads from both sides until
// finding a difference (or 0), we might get a spurious page fault by
// reading bytes past the difference. To avoid this, we never do a load
// that crosses a page boundary.
#definekShort20// too short for vectors (must be >16)
.text
.globl _strncmp
.align 4
_strncmp:// int strncmp(const char *s1, const char *s2, size_t len);
pushl%esi
pushl%edi
movl20(%esp),%ecx// get length
movl12(%esp),%esi// get LHS ptr
movl16(%esp),%edi// get RHS ptr
push%ebx
cmpl$(kShort),%ecx// worth accelerating?
jaLNotShort// yes
// Too short to bother with parallel compares. Loop over bytes.
//%esi = LHS ptr
//%edi = RHS ptr
//%ecx = length (<= kShort)
LShort:
testl%ecx,%ecx// 0-length?
jnzLShortLoop// no
jmpLReturn0// yes, return 0
.align4,0x90// align inner loops to optimize I-fetch
LShortLoop:// loop over bytes
movzb(%esi),%eax// get LHS byte
movzb(%edi),%ebx// get RHS byte
incl%esi
incl%edi
testl%eax,%eax// LHS==0 ?
jzLNotEqual// yes, this terminates comparison
subl%ebx,%eax// compare them
jnzLExit// done if not equal
decl%ecx// decrement length
jnzLShortLoop
LReturn0:
xorl%eax,%eax// all bytes equal, so return 0
LExit:// return value is in %eax
popl%ebx
popl%edi
popl%esi
ret
LNotEqual:// LHS in eax, RHS in ebx
subl%ebx,%eax// generate return value (nonzero)
popl%ebx
popl%edi
popl%esi
ret
// Loop over bytes until we reach end of a page.
//%esi = LHS ptr
//%edi = RHS ptr
//%ecx = length remaining after end of loop (ie, already adjusted)
//%edx = #bytes until next page (1..15)
.align4,0x90// align inner loops to optimize I-fetch
LLoopOverBytes:
movzb(%esi),%eax// get LHS byte
movzb(%edi),%ebx// get RHS byte
inc%esi
inc%edi
testl%eax,%eax// LHS==0 ?
jzLNotEqual// yes, this terminates comparison
subl%ebx,%eax// compare them
jnzLExit// done if not equal
dec%edx// more to go?
jnzLLoopOverBytes
// Long enough to justify overhead of setting up vector compares. In order to
// avoid spurious page faults, we loop over:
//
//min( length, bytes_in_LHS_page, bytes_in_RHS_page) >> 4
//
// 16-byte chunks. When we near a page end, we have to revert to a byte-by-byte
// comparison until reaching the next page, then resume the vector comparison.
//%esi = LHS ptr
//%edi = RHS ptr
//%ecx = length (> kShort)
LNotShort:
movl%esi,%eax// copy ptrs
movl%edi,%edx
andl$4095,%eax// mask down to page offsets
andl$4095,%edx
cmpl%eax,%edx// which is bigger?
cmova%edx,%eax// %eax = max(LHS offset, RHS offset);
movl$4096,%edx
subl%eax,%edx// get #bytes to next page crossing
cmpl%ecx,%edx// will operand run out first?
cmova%ecx,%edx// get min(length remaining, bytes to page end)
movl%edx,%eax
shrl$4,%edx// get #chunks till end of operand or page
jnzLLoopOverChunks// enter vector loop
// Too near page end for vectors.
subl%eax,%ecx// adjust length remaining
movl%eax,%edx// %edx <- #bytes to page end
cmpl$(kShort),%ecx// will there be enough after we cross page for vectors?
jaLLoopOverBytes// yes
addl%eax,%ecx// no, restore total length remaining
jmpLShortLoop// compare rest byte-by-byte (%ecx != 0)
// Loop over 16-byte chunks.
//%esi = LHS ptr
//%edi = RHS ptr
//%ecx = length remaining
//%edx = chunk count
.align4,0x90// align inner loops to optimize I-fetch
LLoopOverChunks:
movdqu(%esi),%xmm1// get LHS
movdqu(%edi),%xmm2// get RHS
pxor%xmm0,%xmm0// get some 0s in the shadow of the loads
addl$16,%esi
pcmpeqb%xmm1,%xmm2// compare LHS to RHS
pcmpeqb%xmm1,%xmm0// compare LHS to 0s
addl$16,%edi
pmovmskb %xmm2,%eax// get result mask for comparison of LHS and RHS
pmovmskb %xmm0,%ebx// get result mask for 0 check
subl$16,%ecx// decrement length remaining
xorl$0xFFFF,%eax// complement compare mask so 1 means "not equal"
orl%ebx,%eax// combine the masks and check for 1-bits
jnzLFoundDiffOr0// we found differing bytes or a 0-byte
dec%edx// more to go?
jnzLLoopOverChunks// yes
cmpl$(kShort),%ecx// a lot more to compare?
jbeLShort// no
jmpLNotShort// compute distance to next page crossing etc
// Found a zero and/or a difference in vector compare.
//%esi = LHS ptr, already advanced by 16
//%edi = RHS ptr, already advanced by 16
//%eax = bit n set if bytes n differed or were 0
LFoundDiffOr0:
bsf%eax,%edx// which byte differed or was 0?
subl$16,%esi// point to start of vectors while we wait for bit scan
subl$16,%edi
movzb(%esi,%edx),%eax// get LHS byte
movzb(%edi,%edx),%ecx// get RHS byte
popl%ebx
popl%edi
subl%ecx,%eax// compute difference (ie, return value)
popl%esi
ret
branches/cparm/i386/libsa/string.c
2525
2626
2727
28
2928
3029
30
3131
3232
3333
......
9191
9292
9393
94
9594
9695
9796
......
170169
171170
172171
172
173173
174174
175175
......
200200
201201
202202
203
203204
204205
205206
206207
207208
208209
210
211
209212
210213
211214
......
277280
278281
279282
283
284
280285
281286
282287
......
311316
312317
313318
319
314320
315321
316322
......
334340
335341
336342
343
344
337345
338346
339347
......
351359
352360
353361
362
363
354364
355365
356366
......
585595
586596
587597
598
588599
589600
590601
......
601612
602613
603614
604
615
605616
606617
607618
#include "libsa.h"
static int _mach_strlen(const char *str);
static char *STRDUP(const char *string);
#if 0
/*
* Abstract:
* strcmp (s1, s2) compares the strings "s1" and "s2".
return 0;
}
/*
* Abstract:
* strcpy copies the contents of the string "from" including
return(s - src - 1);/* count does not include NUL */
}
#endif
/*
* History:
return (const char *) (in - 1);
}
#if 0
void *
memmove(void *dst, const void *src, size_t ulen)
{
bcopy(src, dst, ulen);
return dst;
}
#endif
#if UNUSED
int
ptol(const char *str)
return str;
}
#endif
#if 0
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
return(dlen + (s - src)); /* count does not include NUL */
}
#endif
/*
*
return(os1);
}
#if 0
static int _mach_strlen(const char *str);
static int
_mach_strlen(const char *str)
{
{
return (size_t)_mach_strlen(str);
}
#endif
#if UNUSED
/*
* Does the same thing as strlen, except only looks up
* SUCH DAMAGE.
*/
#if 0
/*
* Compare memory regions.
*/
}
return (0);
}
#endif
/*
* Perform a binary search.
*
branches/cparm/i386/libsa/memset.s
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
/*
* Copyright (c) 2005 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@
*/
/* This file contains the following functions:
*
*void *memset(void *b, int c, size_t len);
*void memset_pattern4(void *b, const void *c4, size_t len);
*void memset_pattern8(void *b, const void *c8, size_t len);
*void memset_pattern16(void *b, const void *c16, size_t len);
*
* Calls of memset() with c==0 are routed to the bzero() routine. Most of the
* others go to _memset_pattern, which is entered as follows:
*%edi = ptr to memory to set (aligned)
*%edx = length (which can be short, though we bias in favor of long operands)
*%xmm0 = the pattern to store
* Return conditions:
*%eax, %edi, %esi, %ecx, and %edx all trashed
*
* NB: we avoid "stos" family of instructions (stosl, stosb), as they are very slow
* on P4s and probably other processors.
*/
#define kShort255// for nonzero memset(), too short for commpage
.text
.globl_memset
.align2
_memset:// void *memset(void *b, int c, size_t len);
movl8(%esp),%eax// get 1-byte pattern
movl12(%esp),%edx// get length
andl$0xFF,%eax// (c==0) ?
jnzLNonzero// not a bzero
movl%edx,8(%esp)// put count where bzero() expects it
jmp_bzero// enter _bzero
// Handle memset of a nonzero value.
LNonzero:
pushl%edi// save a few nonvolatiles
pushl%esi
movl%eax,%esi// replicate byte in %al into all four bytes
movl12(%esp),%edi// point to operand
shll$8,%esi
orl%esi,%eax
movl%eax,%esi
shll$16,%esi
orl%esi,%eax// now %eax has "c" in all 4 bytes
cmpl$(kShort),%edx// is operand too short for SSE?
jaLCallCommpage// no
// Nonzero memset() too short to call commpage.
//%eax = replicated 4-byte pattern
//%edi = ptr
//%edx = length (<= kShort)
cmpl$16,%edx// long enough to word align?
jge3f// yes
test%edx,%edx// length==0?
jz6f
1:
movb%al,(%edi)// pack in a byte
inc%edi
dec%edx
jnz1b
jmp6f
2:
movb%al,(%edi)// pack in a byte
inc%edi
dec%edx
3:
test$3,%edi// is ptr doubleword aligned?
jnz2b// no
movl%edx,%ecx// copy length
shrl$2,%edx// #doublewords to store
4:
movl%eax,(%edi)// store aligned doubleword
addl$4,%edi
dec%edx
jnz4b
andl$3,%ecx// any leftover bytes?
jz6f// no
5:
movb%al,(%edi)// pack in a byte
inc%edi
dec%ecx
jnz5b
6:
movl12(%esp),%eax// get return value (ie, original ptr)
popl%esi
popl%edi
ret
// Nonzero memset() is long enough to call commpage.
//%eax = replicated 4-byte pattern
//%edi = ptr
//%edx = length (> kShort)
LCallCommpage:
movd%eax,%xmm0// move %eax to low 4 bytes of %xmm0
pshufd$(0x00),%xmm0,%xmm0// replicate across the vector
movl%edi,%ecx// copy dest ptr
negl%ecx
andl$15,%ecx// get #bytes to align ptr
jz2f// skip if already aligned
subl%ecx,%edx// decrement length
1:
movb%al,(%edi)// pack in a byte
inc%edi
dec%ecx
jnz1b
2:// ptr aligned, length long enough to justify
call_memset_pattern // call commpage to do the heavy lifting
movl12(%esp),%eax// get return value (ie, original ptr)
popl%esi
popl%edi
ret
// Handle memset of a 16-byte pattern.
.globl_memset_pattern16
.align2, 0x90
_memset_pattern16:// void memset_pattern16(void *b, const void *c16, size_t len);
pushl%edi
pushl%esi
movl20(%esp),%edx// get length
movl16(%esp),%esi// get ptr to 16-byte pattern
movl12(%esp),%edi// point to operand
movdqu(%esi),%xmm0// load the pattern
jmpLAlignPtr
// Handle memset of an 8-byte pattern.
.globl_memset_pattern8
.align2, 0x90
_memset_pattern8:// void memset_pattern8(void *b, const void *c8, size_t len);
pushl%edi
pushl%esi
movl20(%esp),%edx// get length
movl16(%esp),%esi// get ptr to 8-byte pattern
movl12(%esp),%edi// point to operand
movq(%esi),%xmm0// load pattern into low 8 bytes
punpcklqdq %xmm0,%xmm0// replicate into all 16
jmpLAlignPtr
// Handle memset of a 4-byte pattern.
.globl_memset_pattern4
.align2, 0x90
_memset_pattern4:// void memset_pattern4(void *b, const void *c4, size_t len);
pushl%edi
pushl%esi
movl20(%esp),%edx// get length
movl16(%esp),%esi// get ptr to 4-byte pattern
movl12(%esp),%edi// point to operand
movd(%esi),%xmm0// load pattern into low 4 bytes
pshufd$(0x00),%xmm0,%xmm0// replicate the 4 bytes across the vector
// Align ptr if necessary. We must rotate the pattern right for each byte we
// store while aligning the ptr. Since there is no rotate instruction in SSE3,
// we have to synthesize the rotates.
//%edi = ptr
//%edx = length
//%xmm0 = pattern
LAlignPtr:// NB: can drop down to here!
cmpl$100,%edx// long enough to bother aligning ptr?
movl%edi,%ecx// copy ptr
jbLReady// not long enough
negl%ecx
andl$15,%ecx// get #bytes to align ptr
jzLReady// already aligned
subl%ecx,%edx// adjust length
test$1,%cl// 1-byte store required?
movd%xmm0,%eax// get 4 low bytes in %eax
jz2f// no
movdqa%xmm0,%xmm1// copy pattern so we can shift in both directions
movb%al,(%edi)// pack in the low-order byte
psrldq$1,%xmm0// shift pattern right 1 byte
inc%edi
pslldq$15,%xmm1// shift pattern left 15 bytes
shrl$8,%eax// in case 2-byte store is required
por%xmm1,%xmm0// complete right rotate of pattern by 1 byte
2:
test$2,%cl// 2-byte store required?
jz4f// no
psrldq$2,%xmm0// shift pattern down 2 bytes
movw%ax,(%edi)// pack in next two bytes
pinsrw$7,%eax,%xmm0// insert low word of %eax into high word of %xmm0
addl$2,%edi// adjust ptr
4:
test$4,%cl// 4-byte store required?
jz8f// no
movd%xmm0,(%edi)// store low 4 bytes of %xmm0
pshufd$(0x39),%xmm0,%xmm0// rotate %xmm0 right 4 bytes (mask == 00 11 10 01)
addl$4,%edi// adjust ptr
8:
test$8,%cl// 8-byte store required?
jzLReady// no
movq%xmm0,(%edi)// store low 8 bytes of %xmm0
pshufd$(0x4e),%xmm0,%xmm0// rotate %xmm0 right 8 bytes (mask == 01 00 11 10)
addl$8,%edi// adjust ptr
// Ptr is aligned if practical, we're ready to call commpage to do the heavy lifting.
LReady:
call_memset_pattern // call commpage to do the heavy lifting
popl%esi
popl%edi
ret
branches/cparm/i386/libsa/memory.h
9393
9494
9595
96
97
98
99
100
101
102
96103
97
98
104
99105
100106
101107
#define LOAD_ADDR 0x18100000 // 64M File load buffer
#define LOAD_LEN 0x04000000
#define SANDBOX_ADDR 0x1C100000 // 256M modules sandbox aera,
#define SANDBOX_LEN 0x10000000
#define SANDBOX_PER_MODULE 0x1000000 // 16M per module
#define SANDBOX_MAX_MODULE SANDBOX_LEN/SANDBOX_PER_MODULE // Max nb of module
// Location of data fed to boot2 by the prebooter
#define PREBOOT_DATA 0x1C100000 // Still have enough room for a 63M ramdisk image
// in case of 512MB system memory.
#define PREBOOT_DATA 0x2C100000
#define TFTP_ADDR LOAD_ADDR // tftp download buffer
#define TFTP_LEN LOAD_LEN
branches/cparm/i386/libsa/strlcpy.s
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
/*
* Copyright (c) 2007 Apple Inc. All rights reserved.
*
* @APPLE_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. 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_LICENSE_HEADER_END@
*/
// *****************
// * S T R L C P Y *
// *****************
//
// size_t strlcpy(char *dst, const char *src, size_t size);
//
// We optimize the move by doing it word parallel. This introduces
// a complication: if we blindly did word load/stores until finding
// a 0, we might get a spurious page fault by touching bytes past it.
// To avoid this, we never do a load that crosses a page boundary,
// or store unnecessary bytes.
//
// The test for 0s relies on the following inobvious but very efficient
// word-parallel test:
//x = dataWord + 0xFEFEFEFF
//y = ~dataWord & 0x80808080
//if (x & y) == 0 then no zero found
// The test maps any non-zero byte to zero, and any zero byte to 0x80,
// with one exception: 0x01 bytes preceeding the first zero are also
// mapped to 0x80.
//
// On Core2 class machines, this word-parallel implementation seems to
// be slightly faster than using SSE up to about 100 bytes.
// It is faster than the naive byte-by-byte implementation for
// operands longer than about 8 bytes.
.text
.globl _strlcpy
.align 4
_strlcpy:// size_t *strlcpy(char *dst, const char *src, size_t size);
pushl%edi
pushl%esi
pushl%ebx
movl16(%esp),%edi// get dest ptr
movl20(%esp),%esi// get source ptr
movl24(%esp),%ecx// get length of buffer
movl%esi,%edx// copy source ptr
negl%edx
andl$3,%edx// how many bytes to align source ptr?
jzLAligned// already aligned
// Loop over bytes.
//%edi = dest ptr
//%esi = source ptr
//%ecx = length remaining in buffer
//%edx = number of bytes to copy (>0, may not fit in buffer)
LLoopOverBytes:
movzb(%esi),%eax// get source byte before checking buffer length
testl%ecx,%ecx// buffer full?
jzL0NotFound// yes
inc%esi
dec%ecx
movb%al,(%edi)// pack into dest
inc%edi
testl%eax,%eax// 0?
jzLDone// yes, done
dec%edx// more to go?
jnzLLoopOverBytes
// Source is aligned. Loop over words until end of buffer. We
// align the source, rather than the dest, to avoid getting spurious page faults.
//%edi = dest ptr (unaligned)
//%esi = source ptr (word aligned)
//%ecx = length remaining in buffer
LAligned:
movl$5,%edx// if buffer almost exhausted, prepare to copy rest byte-by-byte
cmpl$4,%ecx// enough for at least one word?
jbLLoopOverBytes
// Loop over words.
//%edi = dest ptr (unaligned)
//%esi = source ptr (word aligned)
//%ecx = length remaining in buffer (>=4)
LLoopOverWords:
movl(%esi),%eax// get next 4 bytes of source
subl$4,%ecx
addl$4,%esi
movl%eax,%edx// make 2 copies of word
movl%eax,%ebx
notl%edx// use magic word-parallel test for 0s
addl$0xFEFEFEFF,%ebx
andl$0x80808080,%edx
testl%ebx,%edx
jnzL0Found// one of the bytes of %eax is a 0
movl%eax,(%edi)// pack 4 bytes into destination
addl$4,%edi
cmpl$4,%ecx// room in buffer for another word?
jaeLLoopOverWords// yes
movl%ecx,%edx// copy leftovers in byte loop
jmpLLoopOverBytes
// Found a 0-byte in the word of source. Store a byte at a time until the 0.
//%edi = dest ptr (unaligned)
//%eax = last word of source, known to have a 0-byte
LNextByte:
shrl$8,%eax// next byte
L0Found:
movb%al,(%edi)// pack in next byte
incl%edi
testb%al,%al// 0?
jnzLNextByte
// Done storing string.
//%edi = ptr to byte after 0-byte
LDone:
subl16(%esp),%edi// subtract original dest ptr to get length stored
decl%edi// don't count the 0-byte
movl%edi,%eax// copy to return value
LExit:
popl%ebx
popl%esi
popl%edi
ret
// Buffer filled but 0-byte not found. We return the length of the source string.
// This is not optimized, as it is an error condition.
//%edi = dest ptr (ie, 1 past end of buffer)
//%esi = source ptr (ptr to 1st byte that does not fit)
L0NotFound:
movl24(%esp),%eax// reload buffer length
testl%eax,%eax// null?
jz1f// yes, cannot store a 0
xorl%edx,%edx// get a 0
movb%dl,-1(%edi)// store a 0 at end of buffer to delimit string
1:
movzb(%esi),%edx// get next byte of source
incl%esi
incl%eax
testl%edx,%edx// 0?
jnz1b
decl%eax// don't count the 0-byte
jmpLExit
branches/cparm/i386/libsa/bcopy_scalar.s
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
/*
* Copyright (c) 2003-2006 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@
*/
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from locore.s.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <architecture/i386/asm_help.h>
/*
* (ov)bcopy (src,dst,cnt)
* ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
*/
LABEL(_bcopy)
pushl %ebp /* set up a frame for backtraces */
movl %esp,%ebp
pushl %esi
pushl %edi
movl 8(%ebp),%esi
movl 12(%ebp),%edi
jmp 1f
LABEL(_memcpy)
LABEL(_memmove)
pushl%ebp/* set up a frame for backtraces */
movl%esp,%ebp
pushl %esi
pushl %edi
movl 8(%ebp),%edi
movl 12(%ebp),%esi
movl %edi,%eax
1:
movl 16(%ebp),%ecx
movl %edi,%edx
subl %esi,%edx
cmpl %ecx,%edx /* overlapping? */
jb 2f
cld /* nope, copy forwards. */
movl %ecx,%edx
shrl $2,%ecx /* copy by words */
rep
movsl
movl %edx,%ecx
andl $3,%ecx /* any bytes left? */
rep
movsb
popl %edi
popl %esi
popl%ebp
ret
2:
addl %ecx,%edi /* copy backwards. */
addl %ecx,%esi
std
movl %ecx,%edx
andl $3,%ecx /* any fractional bytes? */
decl %edi
decl %esi
rep
movsb
movl %edx,%ecx /* copy remainder by words */
shrl $2,%ecx
subl $3,%esi
subl $3,%edi
rep
movsl
popl %edi
popl %esi
popl%ebp
cld
ret
branches/cparm/i386/libsa/strncpy.s
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
/*
* Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_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. 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_LICENSE_HEADER_END@
*/
// *****************
// * S T R N C P Y *
// *****************
//
// char *strncpy(const char *dst, const char *src, size_t n);
//
// We optimize the move by doing it vector parallel. This introduces
// a complication: if we blindly did vector load/stores until finding
// a 0, we might get a spurious page fault by touching bytes past it.
// To avoid this, we never do a load that crosses a page boundary,
// and never store a byte we don't have to.
//
// We align the destination, because unaligned vector stores are slow.
//
// Recall that strncpy() zero fills the remainder of the dest buffer,
// and does not terminate the string if it's length is greater than or
// equal to n.
#definekShort31// too short to bother with vector loop
.text
.globl _strncpy
.align 4
_strncpy:// char *strncpy(const char *dst, const char *src, size_t n);
pushl%edi
pushl%esi
movl12(%esp),%edi// get dest ptr
movl16(%esp),%esi// get source ptr
movl20(%esp),%ecx// get length
movl%edi,%edx// copy dest ptr
negl%edx
andl$15,%edx// how many bytes to align dest ptr?
jnzLCheckShortCopy// align destination first
// In order to avoid spurious page faults, we loop until nearing the source page
// end. Then we revert to a byte-by-byte loop for 16 bytes until the page is crossed,
// then resume the vector loop.
//%esi = source ptr (unaligned)
//%edi = dest ptr (aligned)
//%ecx = buffer length remaining
LNextChunk:// NB: can drop down to here
movl%esi,%eax// copy source ptr
movl$4096,%edx
andl$4095,%eax// get offset into source page
subl%eax,%edx// get #bytes remaining in source page
cmpl%ecx,%edx// will buffer run out before the page end?
cmova%ecx,%edx// get min(length remaining, bytes to page end)
shrl$4,%edx// get #chunks till end of page
jnzLLoopOverChunks// enter vector loop
// We can't use the chunk loop yet. Check for short and empty buffers, then use byte loop.
LCrossPage:// if buffer is large enough, cross source page
movl$16,%edx// move 16 bytes to cross page but keep dest aligned
LCheckShortCopy:// we propose to copy %edx bytes in byte loop
cmpl$(kShort),%ecx// much left?
jaLLoopOverBytes// yes, loop over bytes then more chunks
movl%ecx,%edx// no, use the byte loop for everything
testl%ecx,%ecx// have we filled buffer?
jnzLLoopOverBytes// no
jmpLDone
// Loop over bytes.
//%esi = source ptr
//%edi = dest ptr
//%ecx = buffer length remaining
//%edx = count of bytes to loop over (<= buffer length)
.align4,0x90// align inner loops to optimize I-fetch
LLoopOverBytes:
movzb(%esi),%eax// get source byte
inc%esi
dec%ecx// decrement length
movb%al,(%edi)// pack into dest
inc%edi
testl%eax,%eax// 0?
jzLZeroBuffer// yes, we're done copying string
dec%edx// more to go?
jnzLLoopOverBytes
testl%ecx,%ecx// at end of buffer?
jnzLNextChunk// no, xfer chunks
jmpLDone// yes
// Loop over 16-byte chunks.
//%esi = source ptr (unaligned)
//%edi = dest ptr (aligned)
//%ecx = buffer length remaining
//%edx = chunk count
.align4,0x90// align inner loops to optimize I-fetch
LLoopOverChunks:
movdqu(%esi),%xmm1// get source
pxor%xmm0,%xmm0// get some 0s
addl$16,%esi
pcmpeqb%xmm1,%xmm0// compare source to 0s
pmovmskb %xmm0,%eax// get result mask for 0 check
testl%eax,%eax// any 0s?
jnzLFound0// yes, exit loop
movdqa%xmm1,(%edi)// no 0s so do aligned store into destination
addl$16,%edi
subl$16,%ecx// decrement length remaining
dec%edx// more to go?
jnzLLoopOverChunks
jmpLCrossPage// cross page but keep dest aligned
// Found a zero in the vector. Figure out where it is, and store the bytes
// up to it. It is possible that we should check to be sure (%ecx >= 16), and
// just do an aligned store of %xmm1 if so. But if we did, we'd be doing byte
// stores into the same double quadword in bzero(), which might hit a hazard.
// Experimentation needed.
//%edi = dest ptr (aligned)
//%eax = result mask
//%ecx = buffer length remaining
//%xmm1 = source vector
LFound0:
bsf%eax,%edx// find first 0
subl%edx,%ecx// decrement remaining buffer length
test$8,%dl// 8-byte store required?
jz4f// no
movq%xmm1,(%edi)// pack in 8 low bytes
psrldq$8,%xmm1// then shift vector down 8 bytes
addl$8,%edi
4:
test$4,%dl// 4-byte store required?
jz3f// no
movd%xmm1,(%edi)// pack in 4 low bytes
psrldq$4,%xmm1// then shift vector down 4 bytes
addl$4,%edi
3:
andl$3,%edx// more to go?
jzLZeroBuffer// no
movd%xmm1,%eax// move remainders out of vector into %eax
1:// loop on up to three bytes
movb%al,(%edi)// pack in next byte
shrl$8,%eax// shift next byte into position
inc%edi
dec%edx
jnz1b
// We've copied the string. Now zero the rest of the buffer, using commpage bzero().
//%edi = dest ptr
//%ecx = buffer length remaining
LZeroBuffer:
pushl%ecx// remaining buffer size
pushl%edi// ptr to 1st unstored byte
call_bzero
addl$8,%esp// pop off the arguments
LDone:
movl12(%esp),%eax// original dest ptr is return value
popl%esi
popl%edi
ret
branches/cparm/i386/libsa/bzero_scalar.s
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
/*
* Copyright (c) 2003-2006 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@
*/
/*
* Copyright (c) 1993 Winning Strategies, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Winning Strategies, Inc.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <architecture/i386/asm_help.h>
/*
* bzero (void *b, size_t len)
* write len zero bytes to the string b.
*
* Written by:
* J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
*/
LABEL(_bzero)
pushl%ebp/* set up a frame for backtraces */
movl%esp,%ebp
pushl %edi
pushl %ebx
movl 8(%ebp),%edi
movl 12(%ebp),%ecx
cld /* set fill direction forward */
xorl %eax,%eax /* set fill data to 0 */
/*
* if the string is too short, it's really not worth the overhead
* of aligning to word boundries, etc. So we jump to a plain
* unaligned set.
*/
cmpl $0x0f,%ecx
jbe L1
movl %edi,%edx /* compute misalignment */
negl %edx
andl $3,%edx
movl %ecx,%ebx
subl %edx,%ebx
movl %edx,%ecx /* zero until word aligned */
rep
stosb
movl %ebx,%ecx /* zero by words */
shrl $2,%ecx
rep
stosl
movl %ebx,%ecx
andl $3,%ecx /* zero remainder by bytes */
L1: rep
stosb
popl %ebx
popl %edi
popl%ebp
ret
branches/cparm/i386/libsa/strlen.s
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
/*
* Copyright (c) 2005 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@
*/
/*
* Strlen, for processors with SSE3.
*
* Note that all memory references must be aligned, in order to avoid spurious
* page faults. Thus we have to load the aligned 16-byte chunk containing the
* first byte of the operand, then mask out false 0s that may occur before the
* first byte.
*
* We favor the fall-through (ie, short operand) path.
*/
.text
.globl _strlen
.align 4, 0x90
_strlen:// size_t strlen(char *b);
movl4(%esp),%edx// get ptr to string
pxor%xmm0,%xmm0// zero %xmm0
movl%edx,%ecx// copy ptr
andl$(-16),%edx// 16-byte align ptr
orl$(-1),%eax
pcmpeqb(%edx),%xmm0// check whole qw for 0s
andl$15,%ecx// get #bytes in aligned dq before operand
shl%cl,%eax// create mask for the bytes of aligned dq in operand
pmovmskb %xmm0,%ecx// collect mask of 0-bytes
andl%eax,%ecx// mask out any 0s that occur before 1st byte
jzLEnterLoop// no 0-bytes (ie, 1-bits), so enter by-16 loop
// We've found a 0-byte.
//%edx = aligned address of 16-byte block containing the terminating 0-byte
//%ecx = compare bit vector
LFoundIt:
bsf%ecx,%eax// find first 1-bit (ie, first 0-byte)
movl4(%esp),%ecx// recover ptr to 1st byte in string
addl%edx,%eax// get address of the 0-byte
subl%ecx,%eax// subtract address of 1st byte to get string length
ret
// Loop over aligned 16-byte blocks:
//%edx = address of previous block
LEnterLoop:
pxor%xmm0,%xmm0// get some 0-bytes
addl$16,%edx// advance ptr
LLoop:
movdqa(%edx),%xmm1// get next chunk
addl$16,%edx
pcmpeqb%xmm0,%xmm1// check for 0s
pmovmskb %xmm1,%ecx// collect mask of 0-bytes
test%ecx,%ecx// any 0-bytes?
jzLLoop// no 0-bytes, so get next dq
subl$16,%edx// back up ptr
jmpLFoundIt
branches/cparm/i386/libsa/strcmp.s
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
/*
* Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_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. 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_LICENSE_HEADER_END@
*/
// ***************
// * S T R C M P *
// ***************
//
// intstrcmp(const char *s1, const char *s2);
//
// We optimize the compare by doing it in parallel, using SSE. This introduces
// a complication: if we blindly did vector loads from both sides until
// finding a difference (or 0), we might get a spurious page fault by
// reading bytes past the difference. To avoid this, we never do a load
// that crosses a page boundary.
.text
.globl _strcmp
.align 4
_strcmp:// int strcmp(const char *s1,const char *s2);
pushl%esi
pushl%edi
movl12(%esp),%esi// get LHS ptr
movl16(%esp),%edi// get RHS ptr
// In order to avoid spurious page faults, we loop over:
//
//min( bytes_in_LHS_page, bytes_in_RHS_page) >> 4
//
// 16-byte chunks. When we near a page end, we have to revert to a byte-by-byte
// comparison until reaching the next page, then resume the vector comparison.
//%esi = LHS ptr
//%edi = RHS ptr
LNextChunk:
movl%esi,%eax// copy ptrs
movl%edi,%edx
andl$4095,%eax// mask down to page offsets
andl$4095,%edx
cmpl%eax,%edx// which is bigger?
cmova%edx,%eax// %eax = max(LHS offset, RHS offset);
movl$4096,%edx
subl%eax,%edx// get #bytes to next page crossing
movl%edx,%eax
shrl$4,%edx// get #chunks till end of operand or page
jnzLLoopOverChunks// enter vector loop
movl%eax,%edx// no chunks...
jmpLLoopOverBytes// ...so loop over bytes until page end
// Loop over bytes.
//%esi = LHS ptr
//%edi = RHS ptr
//%edx = byte count
.align4,0x90// align inner loops to optimize I-fetch
LLoopOverBytes:
movzb(%esi),%eax// get LHS byte
movzb(%edi),%ecx// get RHS byte
inc%esi
inc%edi
testl%eax,%eax// 0?
jzLExit0// yes, we're done
subl%ecx,%eax// compare them
jnzLExit// done if not equal
dec%edx// more to go?
jnzLLoopOverBytes
jmpLNextChunk// we've come to end of page
// Loop over 16-byte chunks.
//%esi = LHS ptr
//%edi = RHS ptr
//%edx = chunk count
.align4,0x90// align inner loops to optimize I-fetch
LLoopOverChunks:
movdqu(%esi),%xmm1// get LHS
movdqu(%edi),%xmm2// get RHS
pxor%xmm0,%xmm0// get some 0s in the shadow of the loads
addl$16,%esi
pcmpeqb%xmm1,%xmm2// compare LHS to RHS
pcmpeqb%xmm1,%xmm0// compare LHS to 0s
addl$16,%edi
pmovmskb %xmm2,%eax// get result mask for comparison of LHS and RHS
pmovmskb %xmm0,%ecx// get result mask for 0 check
xorl$0xFFFF,%eax// complement compare mask so 1 means "not equal"
orl%ecx,%eax// combine the masks and check for 1-bits
jnzLFoundDiffOr0// we found differing bytes or a 0-byte
dec%edx// more to go?
jnzLLoopOverChunks
jmpLNextChunk// compare up to next page boundary
// Found a zero and/or a difference in vector compare.
//%esi = LHS ptr, already advanced by 16
//%edi = RHS ptr, already advanced by 16
//%eax = bit n set if bytes n differed or were 0
LFoundDiffOr0:
bsf%eax,%edx// which byte differed or was 0?
subl$16,%esi// point to start of vectors while we wait for bit scan
subl$16,%edi
movzb(%esi,%edx),%eax// get LHS byte
movzb(%edi,%edx),%ecx// get RHS byte
subl%ecx,%eax// compute difference (ie, return value)
popl%edi
popl%esi
ret
// Found a zero and/or difference in byte loop.
//%eax = LHS byte
//%ecx = RHS byte
LExit0:
subl%ecx,%eax// compute difference (ie, return value)
LExit:// here with difference already in %eax
popl%edi
popl%esi
ret
branches/cparm/i386/libsa/Makefile
2525
2626
2727
28
28
2929
3030
3131
32
32
3333
3434
3535
VPATH = $(OBJROOT):$(SYMROOT)
SA_OBJS = qdivrem.o umoddi3.o udivdi3.o divdi3.o moddi3.o bzero.o bcopy.o printf.o zalloc.o\
SA_OBJS = qdivrem.o umoddi3.o udivdi3.o divdi3.o moddi3.o __bzero.o bzero_scalar.o strcmp.o strcpy.o strncpy.o strlcpy.o strncmp.o strlcat.o bcopy_scalar.o memcmp.o memset.o memset_pattern_sse2.o strlen.o printf.o zalloc.o\
string.o strtol.o \
setjmp.o qsort.o efi_tables.o
SFILES = setjmp.s bzero.s bcopy.s
SFILES = setjmp.s bzero.s bcopy.s __bzero.s bzero_scalar.s strcmp.s strcpy.s strncpy.s strlcpy.s strncmp.s strlcat.s memcmp.s memset.s memset_pattern_sse2.s strlen.s
CFILES = qdivrem.c umoddi3.c udivdi3.c divdi3.c moddi3.c prf.c printf.c zalloc.c \
string.c strtol.c \
qsort.c efi_tables.c
branches/cparm/i386/libsa/strlcat.s
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
/*
* Copyright (c) 2007 Apple Inc. All rights reserved.
*
* @APPLE_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. 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_LICENSE_HEADER_END@
*/
// *****************
// * S T R L C A T *
// *****************
//
// size_t strlcat(char *dst, const char *src, size_t size);
//
// We use SSE to do the initial strlen(), and word-parallel copies
// to do the move. This appears to be faster than either all SSE
// or all word-parallel, at least on Core2 class machines.
//
// Using 4- or 16-byte parallel loops introduce a complication:
// if we blindly did parallel load/stores until finding
// a 0, we might get a spurious page fault by touching bytes past it.
// To avoid this, we never do a load that crosses a page boundary,
// or store unnecessary bytes.
//
// The word parallel test for 0s relies on the following inobvious
// but very efficient test:
//x = dataWord + 0xFEFEFEFF
//y = ~dataWord & 0x80808080
//if (x & y) == 0 then no zero found
// The test maps any non-zero byte to zero, and any zero byte to 0x80,
// with one exception: 0x01 bytes preceeding the first zero are also
// mapped to 0x80.
//
// On Core2 class machines, this algorithm seems to be faster than the
// naive byte-by-byte version for operands longer than about 10 bytes.
.text
.globl _strlcat
.align 4
_strlcat:// size_t *strlcat(char *dst, const char *src, size_t size);
pushl%edi
pushl%esi
pushl%ebx
movl16(%esp),%edi// get dest ptr
movl20(%esp),%esi// get source ptr
movl24(%esp),%ebx// get length of buffer
// Use SSE to find the 0-byte at current end of buffer.
// This is just a minor variant of strlen().
movl%edi,%ecx// copy buffer ptr
andl$(-16),%edi// 16-byte align buffer ptr
pxor%xmm0,%xmm0// get some 0s
andl$15,%ecx// get #bytes in dq before start of buffer
movl$16,%edx
orl$(-1),%eax
subl%ecx,%edx// #bytes from buffer start to end of dq
subl%edx,%ebx// does buffer end before end of dq?
jbLShortBuf1// yes, drop into byte-by-byte mode
movdqa(%edi),%xmm1// get first aligned chunk of buffer
addl$16,%edi
pcmpeqb%xmm0,%xmm1// check for 0s
shl%cl,%eax// create mask for the bytes of aligned dq in operand
pmovmskb %xmm1,%ecx// collect mask of 0-bytes
andl%eax,%ecx// mask out any 0s that occur before buffer start
jnz2f// found end of buffer
1:
subl$16,%ebx// another dq in buffer?
jbLShortBuf2// no, drop into byte-by-byte mode
movdqa(%edi),%xmm1// get next chunk
addl$16,%edi
pcmpeqb%xmm0,%xmm1// check for 0s
pmovmskb %xmm1,%ecx// collect mask of 0-bytes
testl%ecx,%ecx// any 0-bytes?
jz1b// no
2:
bsf%ecx,%edx// find first 1-bit (ie, first 0-byte)
subl$16,%edi// back up ptr into buffer
addl$16,%ebx// recover length remaining as of start of dq
addl%edx,%edi// point to 0-byte
subl%edx,%ebx// compute #bytes remaining in buffer
// Copy byte-by-byte until source is 4-byte aligned.
//%edi = points to 1st byte available in buffer
//%esi = src ptr
//%ebx = buffer length remaining (ie, starting at %edi)
//
// NB: the rest of this code is cut-and-pasted from strlcpy().
movl%esi,%edx// copy source ptr
negl%edx
andl$3,%edx// how many bytes to align source ptr?
jzLAligned// already aligned
// Loop over bytes.
//%edi = dest ptr
//%esi = source ptr
//%ebx = length remaining in buffer
//%edx = number of bytes to copy (>0, may not fit in buffer)
LLoopOverBytes:
movzb(%esi),%eax// get source byte before checking buffer length
testl%ebx,%ebx// buffer full?
jzL0NotFound// yes
inc%esi
dec%ebx
movb%al,(%edi)// pack into dest
inc%edi
testl%eax,%eax// 0?
jzLDone// yes, done
dec%edx// more to go?
jnzLLoopOverBytes
// Source is aligned. Loop over words until end of buffer. We
// align the source, rather than the dest, to avoid getting spurious page faults.
//%edi = dest ptr (unaligned)
//%esi = source ptr (word aligned)
//%ebx = length remaining in buffer
LAligned:
movl$5,%edx// if buffer almost exhausted, prepare to copy rest byte-by-byte
cmpl$4,%ebx// enough for at least one word?
jbLLoopOverBytes
// Loop over words.
//%edi = dest ptr (unaligned)
//%esi = source ptr (word aligned)
//%ebx = length remaining in buffer (>=4)
LLoopOverWords:
movl(%esi),%eax// get next 4 bytes of source
subl$4,%ebx
addl$4,%esi
movl%eax,%edx// make 2 copies of word
movl%eax,%ecx
notl%edx// use magic word-parallel test for 0s
addl$0xFEFEFEFF,%ecx
andl$0x80808080,%edx
testl%ecx,%edx
jnzL0Found// one of the bytes of %eax is a 0
movl%eax,(%edi)// pack 4 bytes into destination
addl$4,%edi
cmpl$4,%ebx// room in buffer for another word?
jaeLLoopOverWords// yes
movl%ebx,%edx// copy leftovers in byte loop
jmpLLoopOverBytes
// Found a 0-byte in the word of source. Store a byte at a time until the 0.
//%edi = dest ptr (unaligned)
//%eax = last word of source, known to have a 0-byte
LNextByte:
shrl$8,%eax// next byte
L0Found:
movb%al,(%edi)// pack in next byte
incl%edi
testb%al,%al// 0?
jnzLNextByte
// Done storing string.
//%edi = ptr to byte after 0-byte
LDone:
subl16(%esp),%edi// subtract original dest ptr to get length stored
decl%edi// don't count the 0-byte
movl%edi,%eax// copy to return value
LExit:
popl%ebx
popl%esi
popl%edi
ret
// Buffer filled but 0-byte not found. We return the length of the buffer plus the length
// of the source string. This is not optimized, as it is an error condition.
//%edi = dest ptr (ie, 1 past end of buffer)
//%esi = source ptr (ptr to 1st byte that does not fit)
L0NotFound:
movl24(%esp),%eax// reload buffer length
testl%eax,%eax// null?
jzLScanSourceTo0// yes, cannot store a 0
xorl%edx,%edx// get a 0
movb%dl,-1(%edi)// store a 0 at end of buffer to delimit string
LScanSourceTo0:
movzb(%esi),%edx// get next byte of source
incl%esi
incl%eax
testl%edx,%edx// 0?
jnzLScanSourceTo0
decl%eax// don't count the 0-byte
jmpLExit
// Buffer too short to reach end of even one 16-byte aligned chunk.
//%esi = src ptr
LShortBuf1:
movl16(%esp),%edi// recover ptr to start of buffer
movl24(%esp),%ebx// recover buffer length
jmpLShortBuf3
// Out of aligned dq's of buffer, 0-byte still not found.
//%esi = src ptr
//%edi = 1st buffer byte not checked for 0
//%ebx = length remaining - 16
LShortBuf2:
addl$16,%ebx// length remaining
LShortBuf3:
movl24(%esp),%eax// recover original buffer length, in case 0-byte not found
movl$17,%edx// buffer almost exhausted, prepare to copy byte-by-byte
1:
testl%ebx,%ebx// no 0s in buffer at all?
jzLScanSourceTo0// yes, cannot store a 0
cmpb$0,(%edi)// is this the 0?
jzLLoopOverBytes// yes, append source
incl%edi
decl%ebx
jmp1b// loop looking for 0
branches/cparm/i386/util/fdisk/user.c
166166
167167
168168
169
169
170170
171171
172172
......
189189
190190
191191
192
192
193193
194194
195195
......
197197
198198
199199
200
200
201201
202202
203203
if (mbr->signature != MBR_SIGNATURE) {
int yn = ask_yn("The signature for this MBR is invalid.\nWould you like to initialize the partition table?", 1);
if (yn) {
strcpy(cmd.cmd, "erase");
strlcpy(cmd.cmd, "erase", sizeof(cmd.cmd));
cmd.args[0] = '\0';
st /* false positive ?? */ = Xerase(&cmd, disk, mbr, tt, offset);
modified = 1;
break;
/* Quick hack to put in '?' == 'help' */
if (!strcmp(cmd.cmd, "?"))
if (!strncmp(cmd.cmd, "?", sizeof("?")))
i = 0;
/* Check for valid command */
printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd);
continue;
} else
strcpy(cmd.cmd, cmd_table[i].cmd);
strlcpy(cmd.cmd, cmd_table[i].cmd, sizeof(cmd.cmd));
/* Call function */
st = cmd_table[i].fcn(&cmd, disk, mbr, tt, offset);
branches/cparm/i386/util/md.c
441441
442442
443443
444
444
445445
446446
447447
if (c) cp[-1]=0;/* end component C style */
/* ignore . */;
if (!strcmp(path_component[i], "."))
if (!strncmp(path_component[i], ".", sizeof(".")))
; /* if "component" != .. */
else /* don't reduce /component/.. to nothing */
i++; /* there could be symbolic links! */
branches/cparm/i386/util/machOconv.c
119119
120120
121121
122
122
123123
124124
125125
case LC_SEGMENT:
#define scp((struct segment_command *)cp)
isDATA = (strcmp(scp->segname, "__DATA") == 0);
isDATA = (strncmp(scp->segname, "__DATA", sizeof("__DATA")) == 0);
if (isDATA)
vmsize = swap(scp->filesize);
else

Archive Download the corresponding diff file

Revision: 2112