📄 mkxsfs.c
字号:
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
#include <memory.h>
#include <xsfs.h>
#include <xsfsstream.h>
#include <xsfstree.h>
#define MAX_NAME 80
// global variables
char sz_bootsect[MAX_NAME] = "bootsect.bin";
char sz_loader[MAX_NAME] = "loader.bin";
char sz_signature[9] = "XSFS ";
char sz_device[MAX_NAME] = "";
int n_scale = 0; // 0 indicates auto
// for image output
int n_image = 0;
int n_sector_size = 512;
#define F_VERBOSE 0x8000
#define F_COMPACT 0x0001
int n_flags = 0; // flags
XSFSDESC xsfs_desc;
// public functions
void LoadBinary(void); // prepare device and buffer
void* GetBuffer(void); // get buffer, buffer is the same size as sector
int BinWrite(int pos); // flush buffer to sector
void FormatBinary(void);
void Cleanup(int errcode); // clean up, errcode = 0 indicates success
static int sw_help(char *argv[])
{
puts("Format Utility for XSFS\n"
"The designing version, by EaseWay\n\n"
"Usage: mkxsfs [switches] device\n"
"Switches:\n"
" -n --scale n_scale specify scale fact\n"
" scale fact is number of sectors in one logical unit\n"
" -b --bootsect file specify boot sector image (default bootsect.bin)\n"
" -l --loader file specify loader image (default loader.bin)\n"
" -s --signature text specify XSFS signature (default XSFS)\n"
" -c --compact-loader set reserved sectors by loader size\n"
" -m --image sectors output to an image (device is filename)\n"
" -t --sector-size size specify sector size (only used with -m --image)\n"
" -h --help display this help\n"
" -v --verbose display details while operation is going on\n\n"
"For any technical supports or bug reports, please contact easeway@163.com");
return 1;
}
static int cvt_int(const char *str)
{
const char *p;
for(p = str; *p; p++)
if(*p<'0' || *p>'9') return -1;
return atoi(str);
}
static int sw_scale(char *argv[])
{
n_scale = cvt_int(argv[1]);
if(n_scale<0)
{ printf("Invalid scale fact %s\n", argv[1]); return 1; }
return 0;
}
static int sw_bootsect(char *argv[])
{
strncpy(sz_bootsect, argv[1], MAX_NAME-1);
sz_bootsect[MAX_NAME-1] = 0;
return 0;
}
static int sw_loader(char *argv[])
{
strncpy(sz_loader, argv[1], MAX_NAME-1);
sz_loader[MAX_NAME-1] = 0;
return 0;
}
static int sw_signature(char *argv[])
{
int i, l = strlen(argv[1]);
strncpy(sz_signature, argv[1], 8);
sz_signature[8]=0;
if(l<8) for(i=l; i<8; i++) sz_signature[i]=' ';
return 0;
}
static int sw_verbose(char *argv[])
{
n_flags|=F_VERBOSE;
return 0;
}
static int sw_compact(char *argv[])
{
n_flags|=F_COMPACT;
return 0;
}
static int sw_image(char *argv[])
{
n_image = cvt_int(argv[1]);
if(n_image<0)
{ printf("Invalid sector number %s\n", argv[1]); return 1; }
if(n_image<128)
{ printf("Sector number must not be less than 128\n"); return 1; }
return 0;
}
static int sw_sector_size(char *argv[])
{
n_sector_size = cvt_int(argv[1]);
if(n_sector_size<=0)
{ printf("Invalid sector size %s\n", argv[1]); return 1; }
return 0;
}
static struct { char name[MAX_NAME]; int argc; int (*pfn)(char *[]); }
def_switches[] = {
{ "-n", 1, sw_scale },
{ "--scale", 1, sw_scale },
{ "-b", 1, sw_bootsect },
{ "--bootsect", 1, sw_bootsect },
{ "-l", 1, sw_loader },
{ "--loader", 1, sw_loader },
{ "-s", 1, sw_signature },
{ "--signature", 1, sw_signature },
{ "-c", 0, sw_compact },
{ "--compact-loader", 0, sw_compact },
{ "-m", 1, sw_image },
{ "--image", 1, sw_image },
{ "-t", 1, sw_sector_size },
{ "--sector-size", 1, sw_sector_size },
{ "-h", 0, sw_help },
{ "--help", 0, sw_help },
{ "-v", 0, sw_verbose },
{ "--verbose", 0, sw_verbose },
{ "", 0, NULL }
};
static int find_switch_proc(const char *arg)
{
int i;
for(i=0; def_switches[i].pfn; i++)
if(strcmp(def_switches[i].name, arg)==0)
return i;
return -1;
}
int main(int argc, char *argv[])
{
int i;
for(i=1; i<argc; i++)
{
if(*argv[i]=='-') // switches
{
int r, entry = find_switch_proc(argv[i]);
if(entry<0)
{ printf("Unknown switch %s\n", argv[i]); return 1; }
if(argc-i-1<def_switches[entry].argc)
{ printf("Too few arguments for %s\n", argv[i]); return 1; }
r = def_switches[entry].pfn(&argv[i]);
if(r!=0) return r;
i+=def_switches[entry].argc;
}
else // treat as device name
{
if(sz_device[0]) // device already specified
{
printf("You have already specified a device %s\n", sz_device);
return 1;
}
else
{
strncpy(sz_device, argv[i], MAX_NAME-1);
sz_device[MAX_NAME-1] = 0;
}
}
}
if(!sz_device[0]) // if device not specified
{
printf("Device not specified\n"
"For help type --help or -h for short\n");
return 1;
}
LoadBinary();
FormatBinary();
Cleanup(0);
return 0;
}
static void fb_system_streams(void)
{
XSFSSTREAM *pStream = (XSFSSTREAM*)GetBuffer();
memset(pStream, 0, xsfs_desc.sector_size);
pStream[SSI_BITMAPHASH].pri_index[0] = xsfs_desc.n_bitmap;
pStream[SSI_FSTREE].pri_index[0] = xsfs_desc.n_bitmap+1;
BinWrite(xsfs_desc.n_reserved);
}
void fb_allocate_bitmap(void)
{
int i, n = xsfs_desc.n_bitmap+2; // 2 means SSI_BITMAPHASH and SSI_FSTREE
void *buf = GetBuffer();
_u32 *pVal = (_u32*)buf;
memset(pVal, 0, xsfs_desc.sector_size);
for(i=0; i<n/32; i++)
{ *pVal = (_u32)-1; pVal ++; }
n %= 32; *pVal = (1<<n) - 1;
BinWrite(xsfs_desc.n_reserved+xsfs_desc.n_ss_desc);
// clear left sectors in unit
for(i=1; i<xsfs_desc.n_bitmap*xsfs_desc.n_scale; i++)
{
memset(buf, 0, xsfs_desc.sector_size);
BinWrite(xsfs_desc.n_reserved+xsfs_desc.n_ss_desc+i);
}
}
void fb_bitmap_hash(void)
{
}
void fb_fstree_root(void)
{
XSFSROOT *root = (XSFSROOT*)GetBuffer();
memset(root, 0, xsfs_desc.sector_size);
root->block_size = DEF_BLOCKSIZE;
root->free_start = 0;
root->n_blocks = 1;
root->n_streams = (root->block_size-sizeof(FSTBLOCK)-sizeof(FSTBLOCKDEF))/(2*sizeof(_u32));
root->start_pos = sizeof(XSFSROOT);
BinWrite(xsfs_desc.n_reserved+xsfs_desc.n_ss_desc+(xsfs_desc.n_bitmap+1)*xsfs_desc.n_scale);
}
void FormatBinary(void)
{
fb_system_streams();
fb_allocate_bitmap();
fb_bitmap_hash();
fb_fstree_root();
}
static void update_basic_xsfs_desc(void)
{
xsfs_desc.version = 0; // this can be changed as this one being updated
xsfs_desc.sector_size = n_sector_size;
xsfs_desc.n_scale = n_scale;
xsfs_desc.n_sectors = n_image;
xsfs_desc.n_units = 0; // should be auto-detected
xsfs_desc.n_reserved = 64; // maximized reserved sectors
xsfs_desc.n_ss_desc = 1;
xsfs_desc.n_bitmap = 0; // should be re-calculated
}
// calculate n_scale and n_units
static void default_units(void)
{
_u32 size;
if(xsfs_desc.n_scale==0) // auto generate scale fact
xsfs_desc.n_scale = (_u16)(xsfs_desc.n_sectors/0x01000000) + 1;
// generally under 16M(8G) 512 bytes per unit is standable
// that will make bitmap as large as 2M
xsfs_desc.n_units = (xsfs_desc.n_sectors-xsfs_desc.n_reserved-xsfs_desc.n_ss_desc)
/ xsfs_desc.n_scale;
size = (_u32)xsfs_desc.sector_size * xsfs_desc.n_scale * 8;
xsfs_desc.n_bitmap = (_u16)(xsfs_desc.n_units / size + (xsfs_desc.n_units%size?1:0));
}
FILE *fp_bs, *fp_loader;
static void load_files(void)
{
long len;
if(!(fp_bs = fopen(sz_bootsect, "rb")))
{ printf("Open bootsect %s failed\n", sz_bootsect); exit(2); }
if(!(fp_loader = fopen(sz_loader, "rb")))
{ fclose(fp_loader); printf("Open loader %s failed\n", sz_loader); exit(2); }
len = filelength(fileno(fp_loader));
if(len/xsfs_desc.sector_size>=xsfs_desc.n_reserved)
{ fclose(fp_bs); fclose(fp_loader); printf("Loader is too large\n"); exit(2); }
if(n_flags&F_COMPACT)
xsfs_desc.n_reserved = (_u16)(len/xsfs_desc.sector_size + (len%xsfs_desc.sector_size?1:0)) + 1;
}
// following code is platform-dependent
#if defined(DJGPP) // MS-DOS environment
#elif defined(_MSC_VER) // MS Visual C++
FILE *fp_binary;
void *p_buffer;
void LoadBinary(void)
{
update_basic_xsfs_desc();
load_files();
fp_binary = fopen(sz_device, n_image ? "wb" : "r+b");
if(!fp_binary)
{
fclose(fp_bs); fclose(fp_loader);
printf("Open device %s failed\n", sz_device);
exit(2);
}
if(n_image==0) // no image is used, sector number should be obtained
{
long len = filelength(fileno(fp_binary));
xsfs_desc.n_sectors = (_u32)(len / xsfs_desc.sector_size);
if(xsfs_desc.n_sectors<128)
{ printf("Device is too small (less than 128 sectors)\n"); exit(2); }
}
default_units();
if(!(p_buffer = malloc(xsfs_desc.sector_size)))
{
fclose(fp_bs); fclose(fp_loader); fclose(fp_binary);
printf("Memory %u bytes required\n", xsfs_desc.sector_size);
exit(2);
}
}
void *GetBuffer(void)
{ return p_buffer; }
int BinWrite(int pos)
{
fseek(fp_binary, pos*xsfs_desc.sector_size, SEEK_SET);
fwrite(p_buffer, xsfs_desc.sector_size, 1, fp_binary);
return 1;
}
void Cleanup(int errcode)
{
if(errcode==0) // OK, all are right
{
int i, l;
// save boot sector
fread(p_buffer, xsfs_desc.sector_size, 1, fp_bs);
// signature
memcpy((char*)p_buffer+3, sz_signature, 9);
// descriptor
memcpy((char*)p_buffer+12, &xsfs_desc, sizeof(xsfs_desc));
// write back
BinWrite(0);
// save loader
for(i=0; i<xsfs_desc.n_reserved-1; i++)
{
l = fread(p_buffer, xsfs_desc.sector_size, 1, fp_loader);
if(l<=0) break;
BinWrite(i+1);
}
}
fclose(fp_bs); fclose(fp_loader); fclose(fp_binary);
free(p_buffer);
if(errcode!=0) exit(errcode);
}
#elif defined(__GNUC__) // Linux
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -