Chameleon

Chameleon Svn Source Tree

Root/branches/zenith432/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;
549default:
550break;
551}
552if (rc < 0)
553unsupported();
554return rc;
555}
556
557/*
558 * Uses statics
559 */
560static
561int checkDevicePath2(char const* pathName)
562{
563DASessionRef session;
564DADiskRef disk;
565CFDictionaryRef descDict;
566CFStringRef s_ref;
567CFBooleanRef b_ref;
568
569assert(pathName);
570if (getDASessionAndDisk(pathName, &session, &disk) < 0)
571return -1;
572descDict = DADiskCopyDescription(disk);
573if (!descDict) {
574CFRelease(disk);
575CFRelease(session);
576fprintf(stderr, "DADiskCopyDescription(%s) returned NULL\n", pathName);
577return -1;
578}
579if (CFDictionaryGetValueIfPresent(descDict, kDADiskDescriptionMediaWholeKey, (void const**) &b_ref) &&
580CFBooleanGetValue(b_ref))
581isMediaWhole = 1;
582if (CFDictionaryGetValueIfPresent(descDict, kDADiskDescriptionMediaLeafKey, (void const**) &b_ref) &&
583CFBooleanGetValue(b_ref))
584isMediaLeaf = 1;
585if (CFDictionaryContainsKey(descDict, kDADiskDescriptionVolumePathKey))
586isVolumeMounted = 1;
587if (CFDictionaryGetValueIfPresent(descDict, kDADiskDescriptionVolumeKindKey, (void const**) &s_ref)) {
588static char cstr_buffer[64];
589char const* cstr = CFStringGetCStringPtr(s_ref, kCFStringEncodingUTF8);
590if (!cstr) {
591CFStringGetCString(s_ref, &cstr_buffer[0], (CFIndex) sizeof cstr_buffer, kCFStringEncodingUTF8);
592cstr = &cstr_buffer[0];
593}
594#if 0
595printf("DAVolumeKind %s\n", cstr);
596#endif
597if (!strcmp(cstr, "exfat"))
598daVolumeKind = _exfat;
599else if (!strcmp(cstr, "hfs"))
600daVolumeKind = _hfs;
601else if (!strcmp(cstr, "msdos"))
602daVolumeKind = _msdos;
603else if (!strcmp(cstr, "ntfs"))
604daVolumeKind = _ntfs;
605else
606daVolumeKind = _other;
607}
608#if 0
609printf(stderr, "whole %c, leaf %c, mounted %c\n",
610 isMediaWhole ? 'Y' : 'N',
611 isMediaLeaf ? 'Y' : 'N',
612 isVolumeMounted ? 'Y' : 'N');
613#endif
614#if 0
615CFShow(descDict);
616#endif
617CFRelease(descDict);
618CFRelease(disk);
619CFRelease(session);
620return 0;
621}
622
623static
624int checkDevicePath(char const* pathName)
625{
626struct stat buf;
627
628assert(pathName);
629if (strncmp(pathName, &devdisk[0], 9) != 0 &&
630strncmp(pathName, &devrdisk[0], 10) != 0) {
631fprintf(stderr, "disk must be of form /dev/rdiskUsS or /dev/diskUsS\ndisk is %s\n", pathName);
632return -1;
633}
634if (stat(pathName, &buf) < 0) {
635fprintf(stderr, "stat on %s failed, %s\n", pathName, strerror(errno));
636return -1;
637}
638if (!(buf.st_mode & (S_IFCHR | S_IFBLK))) {
639fprintf(stderr, "%s is not a block or character special device\n", pathName);
640return -1;
641}
642/*
643 * FIXME: milk information from st_rdev - what's in it?
644 */
645#if 0
646printf("size of buf is %lu\n", sizeof buf);
647printf("st_dev %#x\n", buf.st_dev);
648printf("st_ino %llu\n", buf.st_ino);
649printf("st_mode %#o\n", buf.st_mode);
650printf("st_nlink %u\n", buf.st_nlink);
651printf("st_uid %u\n", buf.st_uid);
652printf("st_gid %u\n", buf.st_gid);
653printf("st_rdev %#x\n", buf.st_rdev);
654printf("st_size %llu\n", buf.st_size);
655printf("st_blocks %llu\n", buf.st_blocks);
656printf("st_blksize %u\n", buf.st_blksize);
657printf("st_flags %#x\n", buf.st_flags);
658printf("st_gen %u\n", buf.st_gen);
659#endif
660return 0;
661}
662
663#pragma mark -
664#pragma mark Usage
665#pragma mark -
666
667static
668void usage(char const* self)
669{
670assert(self);
671fprintf(stderr, "Usage: %s [-yMu] [-f boot_code_file] disk\n", self);
672fprintf(stderr, " boot_code_file is an optional boot template\n");
673fprintf(stderr, " -y: don't ask any questions\n");
674fprintf(stderr, " -M: keep volume mounted while proceeding (useful for root filesystem)\n");
675fprintf(stderr, " -u: force umount (suppresses -M option if given)\n");
676fprintf(stderr, "disk is of the form /dev/rdiskUsS or /dev/diskUsS\n");
677fprintf(stderr, "default boot files are\n");
678fprintf(stderr, " boot1h for HFS+\n");
679fprintf(stderr, " boot1f32 for FAT32\n");
680fprintf(stderr, " boot1x for exFAT\n");
681}
682
683static
684void unsupported(void)
685{
686fprintf(stderr, "%s", &UnsupportedMessage[0]);
687}
688
689#pragma mark -
690#pragma mark Main
691#pragma mark -
692
693int main(int argc, char* const argv[])
694{
695int ch;
696char const* bootFile = NULL;
697char const* devicePath = NULL;
698int dontAsk = 0;
699int keepMounted = 0;
700int forceUmount = 0;
701
702while ((ch = getopt(argc, argv, "yMuf:")) != -1)
703switch (ch) {
704case 'y':
705dontAsk = 1;
706break;
707case 'M':
708keepMounted = 1;
709break;
710case 'u':
711forceUmount = 1;
712break;
713case 'f':
714bootFile = optarg;
715break;
716default:
717goto usage_and_error;
718}
719if (optind + 1 > argc)
720goto usage_and_error;
721devicePath = argv[optind];
722if (geteuid() != 0) {
723fprintf(stderr, "This program must be run as root\n");
724return -1;
725}
726if (forceUmount)
727keepMounted = 0;
728#if 0
729printf("bootFile %s, devicePath %s, dontAsk %d\n", bootFile, devicePath, dontAsk);
730#endif
731if (checkDevicePath(devicePath) < 0)
732return -1;
733if (checkDevicePath2(devicePath) >= 0) {
734if (isMediaWhole && !isMediaLeaf) {
735fprintf(stderr, "%s is a whole disk\n", devicePath);
736return -1;
737}
738switch (daVolumeKind) {
739case _undetected:
740case _exfat:
741case _hfs:
742case _msdos:
743break;
744default:
745unsupported();
746return -1;
747}
748if (isVolumeMounted && keepMounted)
749isVolumeMounted = 0;
750if (isVolumeMounted && umount(devicePath, forceUmount) < 0) {
751if (forceUmount)
752fprintf(stderr, "Unable to force umount %s, please try to umount it manually or reboot\n", devicePath);
753else
754fprintf(stderr, "Unable to umount %s, please 'diskutil umount' manually before running this program,\nor pass -u option to force umount it\n", devicePath);
755return -1;
756}
757}
758/*
759 * Note:
760 * Reading a non-multiple of 512 does not work on /dev/rdisk
761 */
762if (loadChunk(devicePath, daVolumeKind == _hfs ? 1024 : 0, 512, &bpbBlob) < 0)
763goto remount_and_error;
764if (checkSupportedVolume(&daVolumeKind, &bpbBlob, devicePath) < 0)
765goto cleanup_and_error;
766if (!bootFile) {
767switch (daVolumeKind) {
768case _exfat:
769bootFile = &defaultBootFile_exfat[0];
770break;
771case _hfs:
772bootFile = &defaultBootFile_hfs[0];
773break;
774case _msdos:
775bootFile = &defaultBootFile_fat32[0];
776break;
777default:
778assert(0);
779break;
780}
781printf("Using %s as default boot template\n", bootFile);
782}
783
784if (loadChunk(bootFile, 0, 0, &bootBlob) < 0)
785goto cleanup_and_error;
786
787switch (daVolumeKind) {
788case _exfat:
789if (calcSum(&bootBlob, &bpbBlob, &outputBlob, devicePath) < 0)
790goto cleanup_and_error;
791break;
792case _hfs:
793free_buffer(&bpbBlob);
794if (bootBlob._s != 1024U) {
795fprintf(stderr, "Boot Code size must be 1024 bytes\n");
796goto cleanup_and_error;
797}
798break;
799case _msdos:
800if (fat32Layout(&bootBlob, &bpbBlob, &outputBlob) < 0)
801goto cleanup_and_error;
802break;
803default:
804assert(0);
805break;
806}
807if (!dontAsk) {
808printf("About to write new boot record on %s, Are You Sure (Y/N)?", devicePath);
809ch = 0;
810while (ch != 'Y' && ch != 'N')
811ch = getchar();
812if (ch != 'Y') {
813printf("Aborted due to user request\n");
814goto cleanup_and_exit;
815}
816}
817switch (daVolumeKind) {
818case _exfat:
819writeVBR(devicePath, &outputBlob, 2, 12U * 512U, "exFAT");
820break;
821case _hfs:
822writeVBR(devicePath, &bootBlob, 1, 1024U, "HFS+");
823break;
824case _msdos:
825writeVBR(devicePath, &outputBlob, 1, 512U, "FAT32");
826break;
827default:
828assert(0);
829break;
830}
831
832cleanup_and_exit:
833cleanup();
834if (isVolumeMounted)
835mount(devicePath);
836return 0;
837
838cleanup_and_error:
839cleanup();
840remount_and_error:
841if (isVolumeMounted)
842mount(devicePath);
843return -1;
844
845usage_and_error:
846usage(argv[0]);
847return -1;
848}
849

Archive Download this file

Revision: 2596