1/* 2 * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "Volume.h" 8 9#include "boot_block.h" 10#include "compat.h" 11 12// the definitions in fsproto.h (included by kprotos.h) and fs_interface.h 13// (included by Volume.h) are not compatible 14#define get_vnode _get_vnode 15#define put_vnode _put_vnode 16#define new_vnode _new_vnode 17#define remove_vnode _remove_vnode 18#define unremove_vnode _unremove_vnode 19#define notify_listener _notify_listener 20#define send_notification _send_notification 21 22#include "kprotos.h" 23 24#include <string.h> 25#include <stdio.h> 26#include <unistd.h> 27#include <ctype.h> 28 29 30// Note: these structures have been stolen from fs_shell/kernel.c. 31// They shouldn't be used anywhere else 32 33extern vnode_ops fs_entry; 34struct vnode; 35 36struct vnlist { 37 vnode *head; 38 vnode *tail; 39 int num; 40}; 41 42struct nspace { 43 nspace_id nsid; 44 my_dev_t dev; 45 my_ino_t ino; 46 fsystem *fs; 47 vnlist vnodes; 48 void *data; 49 vnode *root; 50 vnode *mount; 51 nspace *prev; 52 nspace *next; 53 char shutdown; 54}; 55 56 57void 58usage(char *programName) 59{ 60 fprintf(stderr, "usage: %s [-vn] [-b block-size] device-path volume-name\n" 61 "Creates a new BFS file system on the specified device (or image)\n" 62 "\t-b\tblock size (defaults to 1024)\n" 63 "\t-n\tdisable indices (long option --noindex)\n" 64 "\t-v\tfor verbose output.\n", 65 programName); 66 67 exit(0); 68} 69 70 71int 72main(int argc, char **argv) 73{ 74 char *programName = argv[0]; 75 if (strrchr(programName, '/')) 76 programName = strrchr(programName, '/') + 1; 77 78 if (argc < 2) 79 usage(programName); 80 81 uint32 blockSize = 1024; 82 uint32 flags = 0; 83 bool verbose = false; 84 85 while (*++argv) { 86 char *arg = *argv; 87 if (*arg == '-') { 88 if (arg[1] == '-') { 89 if (!strcmp(arg, "--noindex")) 90 flags |= VOLUME_NO_INDICES; 91 else 92 usage(programName); 93 } 94 95 while (*++arg && isalpha(*arg)) { 96 switch (*arg) { 97 case 'v': 98 verbose = true; 99 break; 100 case 'b': 101 if (*++argv == NULL || !isdigit(**argv)) 102 usage(programName); 103 104 blockSize = atol(*argv); 105 break; 106 case 'n': 107 flags |= VOLUME_NO_INDICES; 108 break; 109 } 110 } 111 } 112 else 113 break; 114 } 115 116 char *deviceName = argv[0]; 117 if (deviceName == NULL) { 118 fprintf(stderr, "%s: You must at least specify a device where " 119 "the image is going to be created\n", programName); 120 return -1; 121 } 122 123 char *volumeName = "Unnamed"; 124 if (argv[1] != NULL) 125 volumeName = argv[1]; 126 127 if (blockSize != 1024 && blockSize != 2048 && blockSize != 4096 && blockSize != 8192) { 128 fprintf(stderr, "%s: valid block sizes are: 1024, 2048, 4096, and 8192\n", programName); 129 return -1; 130 } 131 132 // set up tiny VFS and initialize the device/image 133 134 init_block_cache(4096, 0); 135 init_vnode_layer(); 136 137 if (install_file_system(&fs_entry, "bfs", 1, -1) == NULL) { 138 printf("can't install my file system\n"); 139 exit(0); 140 } 141 142 struct nspace *mount = (nspace *)malloc(sizeof(nspace)); 143 if (add_nspace(mount, NULL, "bfs", -1, -1) < B_OK) { 144 fprintf(stderr, "%s: add mount structure failed\n", programName); 145 return -1; 146 } 147 148 Volume volume(mount->nsid); 149 status_t status = volume.Initialize(deviceName, volumeName, blockSize, flags); 150 if (status < B_OK) { 151 fprintf(stderr, "%s: Initializing volume failed: %s\n", programName, strerror(status)); 152 return -1; 153 } 154 155 remove_nspace(mount); 156 157 if (verbose) { 158 disk_super_block super = volume.SuperBlock(); 159 160 printf("%s: Disk was initialized successfully.\n", programName); 161 printf("\tname: \"%s\"\n", super.name); 162 printf("\tnum blocks: %Ld\n", super.NumBlocks()); 163 printf("\tused blocks: %Ld\n", super.UsedBlocks()); 164 printf("\tblock size: %lu bytes\n", super.BlockSize()); 165 printf("\tnum allocation groups: %ld\n", super.AllocationGroups()); 166 printf("\tallocation group size: %ld blocks\n", 1L << super.AllocationGroupShift()); 167 printf("\tlog size: %u blocks\n", super.log_blocks.Length()); 168 } 169 170 shutdown_block_cache(); 171 172 // make the disk image bootable 173 174 int device = open(deviceName, O_RDWR); 175 if (device < 0) { 176 fprintf(stderr, "%s: Could not make image bootable: %s\n", programName, strerror(errno)); 177 return -1; 178 } 179 180 // change BIOS drive and partition offset 181 // ToDo: for now, this will only work for images only 182 183 sBootBlockData1[kBIOSDriveOffset] = 0x80; 184 // for now, this should be replaced by the real thing 185 uint32 *offset = (uint32 *)&sBootBlockData1[kPartitionDataOffset]; 186 *offset = 0; 187 188 write_pos(device, 0, sBootBlockData1, kBootBlockData1Size); 189 write_pos(device, kBootBlockData2Offset, sBootBlockData2, kBootBlockData2Size); 190 191 close(device); 192 sync(); 193 194 return 0; 195} 196 197