Chameleon

Chameleon Svn Source Tree

Root/trunk/i386/util/boot1-install/boot1-install.c

1/*
2 * boot1-install.c
3 * boot1-install
4 *
5 * Created by Zenith432 on November 19th, 2014.
6 * Copyright (c) 2014 Zenith432. All rights reserved.
7 *
8 * Modified December 5th, 2014 by Micky1979: Added -u option to force umount.
9 */
10
11#include <assert.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include <errno.h>
17#include <fcntl.h>
18#include <sys/stat.h>
19#include <sys/types.h>
20#include <sys/uio.h>
21#include <unistd.h>
22
23#include <CoreFoundation/CoreFoundation.h>
24#include <DiskArbitration/DiskArbitration.h>
25
26struct buffer_t
27{
28unsigned char* _b;
29size_t _s;
30};
31
32enum volume_kind_t
33{
34_undetected = 0,
35_exfat = 1,
36_hfs = 2,
37_msdos = 3,
38_ntfs = 4,
39_ext4 = 5,
40_other = 255
41};
42
43static int isVolumeMounted = 0;
44static int isMediaWhole = 0;
45static int isMediaLeaf = 0;
46static enum volume_kind_t daVolumeKind = _undetected;
47
48static struct buffer_t bpbBlob = { NULL, 0 };
49static struct buffer_t bootBlob = { NULL, 0 };
50static struct buffer_t outputBlob = { NULL, 0 };
51
52static char const UnsupportedMessage[] = "Only exFAT, FAT32 or HFS+ volumes are supported\n";
53static char const exfatID[] = "EXFAT ";
54static char const fat32ID[] = "FAT32 ";
55static char const devrdisk[] = "/dev/rdisk";
56static char const devdisk[] = "/dev/disk";
57static char const defaultBootFile_exfat[] = "./boot1x";
58static char const defaultBootFile_hfs[] = "./boot1h";
59static char const defaultBootFile_fat32[] = "./boot1f32";
60
61static __used char const copyright[] = "Copyright 2014 Zenith432";
62
63static int checkExfat(struct buffer_t const*);
64static int checkFat32(struct buffer_t const*);
65static int loadChunk(char const*, off_t, off_t, struct buffer_t*);
66static void unsupported(void);
67
68#pragma mark -
69#pragma mark Cleaners
70#pragma mark -
71
72static
73void free_buffer(struct buffer_t* pBuffer)
74{
75assert(pBuffer);
76if (pBuffer->_b) {
77free(pBuffer->_b);
78pBuffer->_b = NULL;
79pBuffer->_s = 0;
80}
81}
82
83/*
84 * Uses statics
85 */
86static
87void cleanup(void)
88{
89free_buffer(&outputBlob);
90free_buffer(&bootBlob);
91free_buffer(&bpbBlob);
92}
93
94#pragma mark -
95#pragma mark ExFAT Processor
96#pragma mark -
97
98static
99unsigned VBRChecksum(unsigned char const* octets, size_t NumberOfBytes)
100{
101unsigned Checksum = 0;
102size_t Index;
103for (Index = 0; Index != NumberOfBytes; ++Index)
104{
105if (Index == 106 || Index == 107 || Index == 112)
106continue;
107Checksum = ((Checksum << 31) | (Checksum >> 1)) + (unsigned) octets[Index];
108}
109return Checksum;
110}
111
112static
113int calcSum(struct buffer_t const* pBootBlob,
114struct buffer_t const* pBpbBlob,
115struct buffer_t* pOutputBlob,
116char const* pathName)
117{
118unsigned char *outBuffer, *p, *q;
119size_t outSize, toCopy, leftOver;
120unsigned Checksum;
121
122assert(pBootBlob && pBpbBlob);
123if (pBootBlob->_s > 9U * 512U) {
124fprintf(stderr, "Boot Code must be at most 4608 bytes\n");
125return -1;
126}
127if (pBpbBlob->_s < 113U) {
128fprintf(stderr, "BPB must be at least 113 bytes\n");
129return -1;
130}
131if (!checkExfat(pBpbBlob)) {
132fprintf(stderr, "BPB does not contain proper exFAT signature\n");
133return -1;
134}
135outSize = 12U * 512U;
136outBuffer = malloc(outSize);
137if (!outBuffer) {
138fprintf(stderr, "%s: Memory allocation failed\n", __FUNCTION__);
139return -1;
140}
141memset(outBuffer, 0, outSize);
142memcpy(outBuffer, pBootBlob->_b, pBootBlob->_s);
143memcpy(&outBuffer[3], &pBpbBlob->_b[3], 8);
144memset(&outBuffer[11], 0, 53);
145toCopy = 120;
146if (pBpbBlob->_s < toCopy)
147toCopy = pBpbBlob->_s;
148leftOver = 120 - toCopy;
149memcpy(&outBuffer[64], &pBpbBlob->_b[64], toCopy - 64);
150if (leftOver)
151memset(&outBuffer[120 - leftOver], 0, leftOver);
152for (toCopy = 0; toCopy != 9; ++toCopy) {
153p = outBuffer + toCopy * 512U + 508U;
154p[2] = 0x55U;
155p[3] = 0xAAU;
156if (toCopy) {
157p[0] = 0U;
158p[1] = 0U;
159}
160}
161if (pathName) {
162/*
163 * Copy OEM Parameters record
164 */
165struct buffer_t auxBlob = { NULL, 0 };
166if (loadChunk(pathName, 9 * 512 , 512, &auxBlob) >= 0) {
167memcpy(&outBuffer[9 * 512], &auxBlob._b[0], 512);
168free_buffer(&auxBlob);
169}
170}
171Checksum = VBRChecksum(outBuffer, 11U * 512U);
172p = outBuffer + 11U * 512U;
173q = p + 512U;
174for (; p < q; p += 4) {
175*(unsigned*) p = Checksum;
176}
177if (pOutputBlob) {
178pOutputBlob->_b = outBuffer;
179pOutputBlob->_s = outSize;
180} else
181free(outBuffer);
182return 0;
183}
184
185#pragma mark -
186#pragma mark FAT32 Processor
187#pragma mark -
188
189static
190int fat32Layout(struct buffer_t const* pBootBlob,
191struct buffer_t const* pBpbBlob,
192struct buffer_t* pOutputBlob)
193{
194unsigned char *outBuffer;
195size_t outSize;
196
197assert(pBootBlob && pBpbBlob);
198if (pBootBlob->_s > 512U) {
199fprintf(stderr, "Boot Code must be at most 512 bytes\n");
200return -1;
201}
202if (pBpbBlob->_s < 90U) {
203fprintf(stderr, "BPB must be at least 90 bytes\n");
204return -1;
205}
206if (!checkFat32(pBpbBlob)) {
207fprintf(stderr, "BPB does not contain proper FAT32 signature\n");
208return -1;
209}
210outSize = 512U;
211outBuffer = malloc(outSize);
212if (!outBuffer) {
213fprintf(stderr, "%s: Memory allocation failed\n", __FUNCTION__);
214return -1;
215}
216memset(outBuffer, 0, outSize);
217memcpy(outBuffer, pBootBlob->_b, pBootBlob->_s);
218memcpy(&outBuffer[3], &pBpbBlob->_b[3], 87);
219outBuffer[510] = 0x55U;
220outBuffer[511] = 0xAAU;
221if (pOutputBlob) {
222pOutputBlob->_b = outBuffer;
223pOutputBlob->_s = outSize;
224} else
225free(outBuffer);
226return 0;
227}
228
229#pragma mark -
230#pragma mark File Operations
231#pragma mark -
232
233static
234void writeVBR(char const* pathName,
235 struct buffer_t const* pBuffer,
236 int numCopies,
237 size_t expectedSize,
238 char const* volumeType)
239{
240int fd, j;
241
242assert(pathName && pBuffer && volumeType);
243if (pBuffer->_s != expectedSize) {
244fprintf(stderr, "Unexpected %s VBR size %lu (expected %lu)\n", volumeType, pBuffer->_s, expectedSize);
245return;
246}
247fd = open(pathName, O_WRONLY);
248if (fd < 0) {
249fprintf(stderr, "Unable to write boot record to %s, %s\n", pathName, strerror(errno));
250}
251for (j = 0; j != numCopies; ++j)
252write(fd, pBuffer->_b, pBuffer->_s);
253close(fd);
254}
255
256static
257int loadChunk(char const* pathName, off_t startOffset, off_t bytesToRead, struct buffer_t* pBuffer)
258{
259int fd;
260ssize_t rc;
261unsigned char* p;
262struct stat buf;
263
264assert(pathName);
265fd = open(pathName, O_RDONLY);
266if (fd < 0) {
267fprintf(stderr, "Unable to open %s, %s\n", pathName, strerror(errno));
268return -1;
269}
270if (bytesToRead > 0)
271buf.st_size = bytesToRead;
272else if (fstat(fd, &buf) < 0) {
273fprintf(stderr, "Unable to fstat %s, %s\n", pathName, strerror(errno));
274close(fd);
275return -1;
276}
277if (startOffset > 0) {
278off_t t = lseek(fd, startOffset, SEEK_SET);
279if (t < 0) {
280fprintf(stderr, "Unable to lseek %s, %s\n", pathName, strerror(errno));
281close(fd);
282return -1;
283}
284if (t != startOffset) {
285fprintf(stderr, "lseek %s returned wrong value %lld instead of %lld\n", pathName, t, startOffset);
286close(fd);
287return -1;
288}
289if (bytesToRead <= 0)
290buf.st_size -= t;
291}
292p = malloc((size_t) buf.st_size);
293if (!p) {
294fprintf(stderr, "%s: Memory allocation failed\n", __FUNCTION__);
295close(fd);
296return -1;
297}
298rc = read(fd, p, (size_t) buf.st_size);
299if (rc < 0) {
300fprintf(stderr, "Unable to read from %s, %s\n", pathName, strerror(errno));
301free(p);
302close(fd);
303return -1;
304}
305close(fd);
306if (rc != buf.st_size) {
307fprintf(stderr, "Unable to read entire chunk from %s, read %ld/%lld\n", pathName, rc, buf.st_size);
308free(p);
309return -1;
310}
311if (pBuffer) {
312pBuffer->_b = p;
313pBuffer->_s = (size_t) rc;
314} else
315free(p);
316return 0;
317}
318
319#pragma mark -
320#pragma mark DiskArbitration Helpers
321#pragma mark -
322
323static
324char const* toBSDName(char const* pathName)
325{
326assert(pathName);
327return strncmp(pathName, &devrdisk[0], 10) ? pathName : &pathName[6];
328}
329
330static
331char const* daReturnStr(DAReturn v)
332{
333if (unix_err(err_get_code(v)) == v)
334return strerror(err_get_code(v));
335switch (v) {
336case kDAReturnError:
337return "Error";
338case kDAReturnBusy:
339return "Busy";
340case kDAReturnBadArgument:
341return "Bad Argument";
342case kDAReturnExclusiveAccess:
343return "Exclusive Access";
344case kDAReturnNoResources:
345return "No Resources";
346case kDAReturnNotFound:
347return "Not Found";
348case kDAReturnNotMounted:
349return "Not Mounted";
350case kDAReturnNotPermitted:
351return "Not Permitted";
352case kDAReturnNotPrivileged:
353return "Not Privileged";
354case kDAReturnNotReady:
355return "Not Ready";
356case kDAReturnNotWritable:
357return "Not Writable";
358case kDAReturnUnsupported:
359return "Unsupported";
360default:
361return "Unknown";
362}
363}
364
365static
366int getDASessionAndDisk(char const* pathName, DASessionRef* pSession, DADiskRef* pDisk)
367{
368DASessionRef session;
369DADiskRef disk;
370
371assert(pathName);
372session = DASessionCreate(kCFAllocatorDefault);
373if (!session) {
374fprintf(stderr, "DASessionCreate returned NULL\n");
375return -1;
376}
377disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, toBSDName(pathName));
378if (!disk) {
379CFRelease(session);
380fprintf(stderr, "DADiskCreateFromBSDName(%s) returned NULL\n", pathName);
381return -1;
382}
383if (pDisk)
384*pDisk = disk;
385else
386CFRelease(disk);
387if (pSession)
388*pSession = session;
389else
390CFRelease(session);
391return 0;
392}
393
394#pragma mark -
395#pragma mark Mount/UMount
396#pragma mark -
397
398static
399void umountCallback(DADiskRef disk __unused,
400DADissenterRef dissenter,
401void *context)
402{
403if (context && dissenter != NULL) {
404*(int*) context = -1;
405fprintf(stderr, "umount unsuccessful, status %s\n", daReturnStr(DADissenterGetStatus(dissenter)));
406}
407CFRunLoopStop(CFRunLoopGetCurrent());
408}
409
410static
411int umount(char const* pathName, int forceUmount)
412{
413DASessionRef session;
414DADiskRef disk;
415int rc;
416
417assert(pathName);
418if (getDASessionAndDisk(pathName, &session, &disk) < 0)
419return -1;
420rc = 0;
421DASessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
422DADiskUnmount(disk, forceUmount ? kDADiskUnmountOptionForce : kDADiskUnmountOptionDefault, umountCallback, &rc);
423CFRunLoopRun();
424DASessionUnscheduleFromRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
425CFRelease(disk);
426CFRelease(session);
427return rc;
428}
429
430static
431void mountCallback(DADiskRef disk __unused,
432 DADissenterRef dissenter,
433 void *context)
434{
435if (context && dissenter != NULL) {
436*(int*) context = -1;
437fprintf(stderr, "mount unsuccessful, status %s\n", daReturnStr(DADissenterGetStatus(dissenter)));
438}
439CFRunLoopStop(CFRunLoopGetCurrent());
440}
441
442static
443int mount(char const* pathName)
444{
445DASessionRef session;
446DADiskRef disk;
447int rc;
448
449assert(pathName);
450if (getDASessionAndDisk(pathName, &session, &disk) < 0)
451return -1;
452rc = 0;
453DASessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
454DADiskMount(disk, NULL, kDADiskMountOptionDefault, mountCallback, &rc);
455CFRunLoopRun();
456DASessionUnscheduleFromRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
457CFRelease(disk);
458CFRelease(session);
459return rc;
460}
461
462#pragma mark -
463#pragma mark Analyze Volume
464#pragma mark -
465
466static
467int checkExfat(struct buffer_t const* pBpbBlob)
468{
469assert(pBpbBlob);
470return !memcmp(&pBpbBlob->_b[3], &exfatID[0], 8);
471}
472
473static
474int checkHFS(struct buffer_t const* pBpbBlob)
475{
476uint16_t sig;
477
478assert(pBpbBlob);
479sig = OSSwapBigToHostInt16(*(uint16_t const*)&pBpbBlob->_b[0]);
480return sig == 0x4244 || sig == 0x482B || sig == 0x4858;/* 'BD', 'H+', 'HX' */
481}
482
483static
484int checkFat32(struct buffer_t const* pBpbBlob)
485{
486uint16_t bytesPerSector, rootEntCnt;
487uint8_t sectorsPerCluster;
488
489assert(pBpbBlob);
490bytesPerSector = OSSwapLittleToHostInt16(*(uint16_t const*)&pBpbBlob->_b[11]);
491if ((bytesPerSector & (bytesPerSector - 1U)) ||
492bytesPerSector < 0x200U ||
493bytesPerSector > 0x1000U)
494return 0;
495sectorsPerCluster = pBpbBlob->_b[13];
496if (!sectorsPerCluster ||
497(sectorsPerCluster & (sectorsPerCluster - 1U)))
498return 0;
499rootEntCnt = OSSwapLittleToHostInt16(*(uint16_t const*)&pBpbBlob->_b[17]);
500if (rootEntCnt)
501return 0;
502return !memcmp(&pBpbBlob->_b[82], &fat32ID[0], 8);
503}
504
505static
506int checkSupportedVolume(enum volume_kind_t* pKind, struct buffer_t const* pBpbBlob, char const* pathName)
507{
508int rc;
509
510assert(pKind && pBpbBlob);
511rc = -1;
512switch (*pKind) {
513case _undetected:
514if (checkExfat(pBpbBlob)) {
515*pKind = _exfat;
516rc = 0;
517} else if (checkFat32(pBpbBlob)) {
518*pKind = _msdos;
519rc = 0;
520} else if (pathName) {
521struct buffer_t auxBlob = { NULL, 0 };
522if (loadChunk(pathName, 1024 , 512, &auxBlob) >= 0) {
523if (checkHFS(&auxBlob)) {
524*pKind = _hfs;
525rc = 0;
526}
527free_buffer(&auxBlob);
528}
529}
530break;
531case _exfat:
532if (checkExfat(pBpbBlob))
533rc = 0;
534else
535*pKind = _other;
536break;
537case _hfs:
538if (checkHFS(pBpbBlob))
539rc = 0;
540else
541*pKind = _other;
542break;
543case _msdos:
544if (checkFat32(pBpbBlob))
545rc = 0;
546else
547*pKind = _other;
548break;
549case _ntfs:
550rc = 0;
551break;
552default:
553break;
554}
555if (rc < 0)
556unsupported();
557return rc;
558}
559
560/*
561 * Uses statics
562 */
563static
564int checkDevicePath2(char const* pathName)
565{
566DASessionRef session;
567DADiskRef disk;
568CFDictionaryRef descDict;
569CFStringRef s_ref;
570CFBooleanRef b_ref;
571
572assert(pathName);
573if (getDASessionAndDisk(pathName, &session, &disk) < 0)
574return -1;
575descDict = DADiskCopyDescription(disk);
576if (!descDict) {
577CFRelease(disk);
578CFRelease(session);
579fprintf(stderr, "DADiskCopyDescription(%s) returned NULL\n", pathName);
580return -1;
581}
582if (CFDictionaryGetValueIfPresent(descDict, kDADiskDescriptionMediaWholeKey, (void const**) &b_ref) &&
583CFBooleanGetValue(b_ref))
584isMediaWhole = 1;
585if (CFDictionaryGetValueIfPresent(descDict, kDADiskDescriptionMediaLeafKey, (void const**) &b_ref) &&
586CFBooleanGetValue(b_ref))
587isMediaLeaf = 1;
588if (CFDictionaryContainsKey(descDict, kDADiskDescriptionVolumePathKey))
589isVolumeMounted = 1;
590if (CFDictionaryGetValueIfPresent(descDict, kDADiskDescriptionVolumeKindKey, (void const**) &s_ref)) {
591static char cstr_buffer[64];
592char const* cstr = CFStringGetCStringPtr(s_ref, kCFStringEncodingUTF8);
593if (!cstr) {
594CFStringGetCString(s_ref, &cstr_buffer[0], (CFIndex) sizeof cstr_buffer, kCFStringEncodingUTF8);
595cstr = &cstr_buffer[0];
596}
597#if 0
598printf("DAVolumeKind %s\n", cstr);
599#endif
600if (!strcmp(cstr, "exfat"))
601daVolumeKind = _exfat;
602else if (!strcmp(cstr, "hfs"))
603daVolumeKind = _hfs;
604else if (!strcmp(cstr, "msdos"))
605daVolumeKind = _msdos;
606else if (!strcmp(cstr, "ntfs"))
607daVolumeKind = _ntfs;
608else
609daVolumeKind = _other;
610}
611#if 0
612printf(stderr, "whole %c, leaf %c, mounted %c\n",
613 isMediaWhole ? 'Y' : 'N',
614 isMediaLeaf ? 'Y' : 'N',
615 isVolumeMounted ? 'Y' : 'N');
616#endif
617#if 0
618CFShow(descDict);
619#endif
620CFRelease(descDict);
621CFRelease(disk);
622CFRelease(session);
623return 0;
624}
625
626static
627int checkDevicePath(char const* pathName)
628{
629struct stat buf;
630
631assert(pathName);
632if (strncmp(pathName, &devdisk[0], 9) != 0 &&
633strncmp(pathName, &devrdisk[0], 10) != 0) {
634fprintf(stderr, "disk must be of form /dev/rdiskUsS or /dev/diskUsS\ndisk is %s\n", pathName);
635return -1;
636}
637if (stat(pathName, &buf) < 0) {
638fprintf(stderr, "stat on %s failed, %s\n", pathName, strerror(errno));
639return -1;
640}
641if (!(buf.st_mode & (S_IFCHR | S_IFBLK))) {
642fprintf(stderr, "%s is not a block or character special device\n", pathName);
643return -1;
644}
645/*
646 * FIXME: milk information from st_rdev - what's in it?
647 */
648#if 0
649printf("size of buf is %lu\n", sizeof buf);
650printf("st_dev %#x\n", buf.st_dev);
651printf("st_ino %llu\n", buf.st_ino);
652printf("st_mode %#o\n", buf.st_mode);
653printf("st_nlink %u\n", buf.st_nlink);
654printf("st_uid %u\n", buf.st_uid);
655printf("st_gid %u\n", buf.st_gid);
656printf("st_rdev %#x\n", buf.st_rdev);
657printf("st_size %llu\n", buf.st_size);
658printf("st_blocks %llu\n", buf.st_blocks);
659printf("st_blksize %u\n", buf.st_blksize);
660printf("st_flags %#x\n", buf.st_flags);
661printf("st_gen %u\n", buf.st_gen);
662#endif
663return 0;
664}
665
666#pragma mark -
667#pragma mark Usage
668#pragma mark -
669
670static
671void usage(char const* self)
672{
673assert(self);
674fprintf(stderr, "Usage: %s [-yMu] [-f boot_code_file] disk\n", self);
675fprintf(stderr, " boot_code_file is an optional boot template\n");
676fprintf(stderr, " -y: don't ask any questions\n");
677fprintf(stderr, " -M: keep volume mounted while proceeding (useful for root filesystem)\n");
678fprintf(stderr, " -u: force umount (suppresses -M option if given)\n");
679fprintf(stderr, "disk is of the form /dev/rdiskUsS or /dev/diskUsS\n");
680fprintf(stderr, "default boot files are\n");
681fprintf(stderr, " boot1h for HFS+\n");
682fprintf(stderr, " boot1f32 for FAT32\n");
683fprintf(stderr, " boot1x for exFAT\n");
684}
685
686static
687void unsupported(void)
688{
689fprintf(stderr, "%s", &UnsupportedMessage[0]);
690}
691
692#pragma mark -
693#pragma mark Main
694#pragma mark -
695
696int main(int argc, char* const argv[])
697{
698int ch;
699char const* bootFile = NULL;
700char const* devicePath = NULL;
701int dontAsk = 0;
702int keepMounted = 0;
703int forceUmount = 0;
704
705while ((ch = getopt(argc, argv, "yMuf:")) != -1)
706switch (ch) {
707case 'y':
708dontAsk = 1;
709break;
710case 'M':
711keepMounted = 1;
712break;
713case 'u':
714forceUmount = 1;
715break;
716case 'f':
717bootFile = optarg;
718break;
719default:
720goto usage_and_error;
721}
722if (optind + 1 > argc)
723goto usage_and_error;
724devicePath = argv[optind];
725if (geteuid() != 0) {
726fprintf(stderr, "This program must be run as root\n");
727return -1;
728}
729if (forceUmount)
730keepMounted = 0;
731#if 0
732printf("bootFile %s, devicePath %s, dontAsk %d\n", bootFile, devicePath, dontAsk);
733#endif
734if (checkDevicePath(devicePath) < 0)
735return -1;
736if (checkDevicePath2(devicePath) >= 0) {
737if (isMediaWhole && !isMediaLeaf) {
738fprintf(stderr, "%s is a whole disk\n", devicePath);
739return -1;
740}
741switch (daVolumeKind) {
742case _undetected:
743case _exfat:
744case _hfs:
745case _msdos:
746case _ntfs:
747break;
748default:
749unsupported();
750return -1;
751}
752if (isVolumeMounted && keepMounted)
753isVolumeMounted = 0;
754if (isVolumeMounted && umount(devicePath, forceUmount) < 0) {
755if (forceUmount)
756fprintf(stderr, "Unable to force umount %s, please try to umount it manually or reboot\n", devicePath);
757else
758fprintf(stderr, "Unable to umount %s, please 'diskutil umount' manually before running this program,\nor pass -u option to force umount it\n", devicePath);
759return -1;
760}
761}
762/*
763 * Note:
764 * Reading a non-multiple of 512 does not work on /dev/rdisk
765 */
766if (loadChunk(devicePath, daVolumeKind == _hfs ? 1024 : 0, 512, &bpbBlob) < 0)
767goto remount_and_error;
768if (checkSupportedVolume(&daVolumeKind, &bpbBlob, devicePath) < 0)
769goto cleanup_and_error;
770if (!bootFile) {
771switch (daVolumeKind) {
772case _exfat:
773bootFile = &defaultBootFile_exfat[0];
774break;
775case _hfs:
776bootFile = &defaultBootFile_hfs[0];
777break;
778case _msdos:
779bootFile = &defaultBootFile_fat32[0];
780break;
781default:
782assert(0);
783break;
784}
785printf("Using %s as default boot template\n", bootFile);
786}
787
788if (loadChunk(bootFile, 0, 0, &bootBlob) < 0)
789goto cleanup_and_error;
790
791switch (daVolumeKind) {
792case _exfat:
793if (calcSum(&bootBlob, &bpbBlob, &outputBlob, devicePath) < 0)
794goto cleanup_and_error;
795break;
796case _hfs:
797free_buffer(&bpbBlob);
798if (bootBlob._s != 1024U) {
799fprintf(stderr, "Boot Code size must be 1024 bytes\n");
800goto cleanup_and_error;
801}
802break;
803case _msdos:
804if (fat32Layout(&bootBlob, &bpbBlob, &outputBlob) < 0)
805goto cleanup_and_error;
806break;
807default:
808assert(0);
809break;
810}
811if (!dontAsk) {
812printf("About to write new boot record on %s, Are You Sure (Y/N)?", devicePath);
813ch = 0;
814while (ch != 'Y' && ch != 'N')
815ch = getchar();
816if (ch != 'Y') {
817printf("Aborted due to user request\n");
818goto cleanup_and_exit;
819}
820}
821switch (daVolumeKind) {
822case _exfat:
823writeVBR(devicePath, &outputBlob, 2, 12U * 512U, "exFAT");
824break;
825case _hfs:
826writeVBR(devicePath, &bootBlob, 1, 1024U, "HFS+");
827break;
828case _msdos:
829writeVBR(devicePath, &outputBlob, 1, 512U, "FAT32");
830break;
831default:
832assert(0);
833break;
834}
835
836cleanup_and_exit:
837cleanup();
838if (isVolumeMounted)
839mount(devicePath);
840return 0;
841
842cleanup_and_error:
843cleanup();
844remount_and_error:
845if (isVolumeMounted)
846mount(devicePath);
847return -1;
848
849usage_and_error:
850usage(argv[0]);
851return -1;
852}
853

Archive Download this file

Revision: 2520