Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2511