/* * Mr Boots Installer * * Installs Mr. Boots onto a generated disk image. * Compile me with your standard C library and for whatever * architecture you feel like running me on, though I much * prefer something simple and 32-bit. */ #include #include #include #include #include /* The EXT2 header is smart enough to know to grab us stdint.h rather than types.h... */ #include "../kernel/include/ext2.h" #define ext2_get_block(block) ((uintptr_t)hdd_dump + (0x400 << sblock->log_block_size) * block) #define ext2_get_block_offset(block) ((0x400 << sblock->log_block_size) * block) char * hdd_dump = NULL; ext2_superblock_t * sblock; ext2_inodetable_t * itable; ext2_inodetable_t * ext2_get_inode( uint32_t inode ) { return (ext2_inodetable_t *)((uintptr_t)itable + sblock->inode_size * (inode - 1)); } ext2_inodetable_t * ext2_finddir( ext2_inodetable_t * rnode, char * name ) { void * block; ext2_dir_t * direntry = NULL; block = (void *)ext2_get_block((rnode->block[0])); uint32_t dir_offset; dir_offset = 0; /* * Look through the requested entries until we find what we're looking for */ while (dir_offset < rnode->size) { ext2_dir_t * d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset); char * dname = malloc(sizeof(char) * (d_ent->name_len + 1)); memcpy(dname, &d_ent->name, d_ent->name_len); dname[d_ent->name_len] = '\0'; if (!strcmp(dname, name)) { free(dname); direntry = d_ent; break; } free(dname); dir_offset += d_ent->rec_len; } if (!direntry) { /* * We could not find the requested entry in this directory. */ fprintf(stderr, "Failed to locate %s!\n", name); return NULL; } else { return ext2_get_inode(direntry->inode); } } /* * Retreive the node for the requested path */ ext2_inodetable_t * iopen( ext2_inodetable_t * root, const char *filename ) { size_t path_len = strlen(filename); if (path_len == 1) { return root; } char * path = (char *)malloc(sizeof(char) * (path_len + 1)); memcpy(path, filename, path_len); char * path_offset = path; uint32_t path_depth = 0; while (path_offset < path + path_len) { if (*path_offset == '/') { *path_offset = '\0'; path_depth++; } path_offset++; } path[path_len] = '\0'; path_offset = path + 1; uint32_t depth; ext2_inodetable_t * node_ptr = root; for (depth = 0; depth < path_depth; ++depth) { node_ptr = ext2_finddir(node_ptr, path_offset); if (!node_ptr) { free((void *)path); return NULL; } else if (depth == path_depth - 1) { return node_ptr; } path_offset += strlen(path_offset) + 1; } free((void *)path); return NULL; } uint32_t ext2_get_inode_block_num( ext2_inodetable_t * inode, uint32_t block ) { if (block < 12) { return inode->block[block]; } else if (block < 12 + (1024 << sblock->log_block_size) / sizeof(uint32_t)) { return *(uint32_t*)((uintptr_t)ext2_get_block(inode->block[12]) + (block - 12) * sizeof(uint32_t)); } return 0; } int main(int argc, char ** argv) { if (argc < 3) { fprintf(stderr, "Expected two additional arguments: a ramdisk, and a file path to second stage to find in it.\n"); return -1; } fprintf(stderr, "I will look for %s in %s and generate appropriate output.\n", argv[2], argv[1]); /* Open sesame! */ FILE * hdd = fopen(argv[1], "r"); fseek(hdd, 0, SEEK_END); /* Get size of file */ uint32_t hdd_size = ftell(hdd); fprintf(stderr, "HDD image is %d bytes.\n", hdd_size); fseek(hdd, 0, SEEK_SET); /* Allocate us up some mems for the hard disk image */ hdd_dump = malloc(sizeof(char) * hdd_size); /* Read 'er in. */ fread(hdd_dump, hdd_size, 1, hdd); /* And lets make us some pointers. */ sblock = (ext2_superblock_t *)((uintptr_t)hdd_dump + 0x400); assert(sblock->magic == EXT2_SUPER_MAGIC); if (sblock->inode_size == 0) { sblock->inode_size = 128; } /* More pointers! */ ext2_bgdescriptor_t * rblock = (ext2_bgdescriptor_t *)((uintptr_t)hdd_dump + 0x400 + 0x400); /* Inode table */ itable = (ext2_inodetable_t *)((uintptr_t)hdd_dump + (0x400 << sblock->log_block_size) * rblock->inode_table); /* Root node */ ext2_inodetable_t * rnode = (ext2_inodetable_t *)((uintptr_t)itable + sblock->inode_size); ext2_inodetable_t * fnode = iopen(rnode, argv[2]); if (!fnode) { fprintf(stderr,"Failed to locate the requested file on the disk image.\n"); return -1; } uint32_t offset = 0x10000; /* Destination offset */ uint32_t _block = 0; uint32_t _block_last = 0; for (uint32_t i = 0; i < fnode->blocks; ++i) { uint32_t block = ext2_get_inode_block_num(fnode, i); if (_block == 0 || block != _block_last + 1) { if (_block != 0) { uint32_t size = (_block_last - _block + 1) * (0x400 << sblock->log_block_size); uint32_t place = ext2_get_block_offset(_block); fprintf(stdout, "read(0x%x, 0x%x, 0x%x, 0x%x);\n", size / 512, place / 512, 0x1000, offset % 0x10000); offset += size; } if (block == 0) { break; } _block = block; } _block_last = block; } }