/* * ReBuild the initial GDT separating the kernel from the user memory * area. * * See the memory layout in the linker script. * * Kernel code starts at 0x100000 (1MB), and is 1 MB long * Kernel data starts at 0x200000 (2MB), and is 1 MB long * Kernel stack starts at 0x400000 (4MB), and is 1 MB long * (Stack grows downwards from 0x400000 to 0x300000) * * But there are other memory areas, esp. low ones (e.g. Video * memory), that we need to access. So the kernel data _segment_ has * to start from lowest memory. :-). * * User area starts from 0x401000 (4MB start offset of stack, and 1 * page size length), and is to the end of the memory. Define two * segments that overlap. We need to control specific * allocation. :-). * * For the moment, merging stack and data segments ... * => kernel code seg starts at 0, and ends at 2 MB! * => kernel data+stack seg starts at 2MB and is 2 MB long */ int initialise_gdt_with_disjoint_kernel_and_user_memory (void) { int retval = FALSE; int i = 0; for (i = 0; i < 8192; i++) global_descriptor_table[i].descriptor = 0; i = set_total_gdt_entries (0); retval = make_descriptor(0, 0, NULL_DESCRIPTOR_FLAGS, 0 ); i = inc_total_gdt_entries (); /* RING_0, DESC_CODEDATA, SEG_EXECUTE_READ, */ retval = make_descriptor ((MEMORYORIGIN), ((KERNELCODESTART + KERNELCODELENGTH)), RING_0_CODEDATA_DESC_READ_EXECUTE, 1 ); i = inc_total_gdt_entries (); /* RING_0, DESC_CODEDATA, SEG_READ_WRITE, */ retval = make_descriptor ((MEMORYORIGIN), (TOTALKERNEL), RING_0_CODEDATA_DESC_READ_WRITE, 2 ); i = inc_total_gdt_entries (); /* RING_3, DESC_CODEDATA, SEG_EXECUTE_READ, */ retval = make_descriptor ((USERMEMORYSTART), MAXMEMPAGES, RING_3_CODEDATA_DESC_READ_EXECUTE, 3 ); i = inc_total_gdt_entries (); /* RING_3, DESC_CODEDATA, SEG_READ_WRITE, */ retval = make_descriptor ((USERMEMORYSTART), MAXMEMPAGES, RING_3_CODEDATA_DESC_READ_WRITE, 4 ); i = get_total_gdt_entries (); load_gdt (); /* Could some status flags tell us if we did ok? */ return retval; }
/* * Build the initial GDT. */ static int initialise_gdt (void) { int retval = FALSE; int i = 0; /* for (i = 0; i < sizeof(global_descriptor_table); i++) */ for (i = 0; i < 8192; i++) global_descriptor_table[i].descriptor = 0; retval = make_descriptor(0, 0, NULL_DESCRIPTOR_FLAGS, 0 ); i = inc_total_gdt_entries (); /* RING_0, DESC_CODEDATA, SEG_EXECUTE_READ, */ retval = make_descriptor ((MEMORYORIGIN), MAXMEMPAGES, RING_0_CODEDATA_DESC_READ_EXECUTE, 1 ); i = inc_total_gdt_entries (); /* RING_0, DESC_CODEDATA, SEG_READ_WRITE, */ retval = make_descriptor ((MEMORYORIGIN), MAXMEMPAGES, RING_0_CODEDATA_DESC_READ_WRITE, 2 ); i = inc_total_gdt_entries (); /* RING_3, DESC_CODEDATA, SEG_EXECUTE_READ, */ retval = make_descriptor ((MEMORYORIGIN), MAXMEMPAGES, RING_3_CODEDATA_DESC_READ_EXECUTE, 3 ); i = inc_total_gdt_entries (); /* RING_3, DESC_CODEDATA, SEG_READ_WRITE, */ retval = make_descriptor ((MEMORYORIGIN), MAXMEMPAGES, RING_3_CODEDATA_DESC_READ_WRITE, 4 ); /* load_gdt (); /\* Could some status flags tell us if we did ok? *\/ */ return retval; }
uint8_t * build_disk(const struct disk_descriptor *desc, uint64_t *disk_size) { struct vmdk_marker marker = { 0 }; struct vmdk_grain_marker gmarker = { 0 }; struct vmdk_sparse_extent_header *header; uint8_t *descriptor; uint8_t *rawdisk, *diskp; uint32_t *gd, *gt; uint64_t extent, gcoverage, gtcoverage, gtsize, gdsize, gtbase; uint32_t block_index; header = make_header(desc->capacity); if (header == NULL) { return NULL; } descriptor = make_descriptor(desc->capacity); if (descriptor == NULL) { free(header); return NULL; } gcoverage = header->grain_size * BYTES_PER_SECTOR; gtcoverage = header->num_gtes_per_gt * gcoverage; gtsize = header->num_gtes_per_gt * sizeof(uint32_t); gdsize = ((header->capacity * BYTES_PER_SECTOR + gtcoverage - 1) / gtcoverage) * sizeof(uint32_t); #define ROUND(x) ((((x) + BYTES_PER_SECTOR - 1) / \ BYTES_PER_SECTOR) * BYTES_PER_SECTOR) /* Compute how much space we need */ extent = 2 * BYTES_PER_SECTOR; /* header + descriptor */ for (block_index = 0, gtbase = 0; block_index < desc->nblocks; block_index++) { if (desc->blocks[block_index].lba >= gtbase) { /* New grain table needed */ extent += ROUND(gtsize) + sizeof(struct vmdk_marker); /* Skip empty grain tables */ while (gtbase <= desc->blocks[block_index].lba) { gtbase += gtcoverage; } } /* Add on size of block */ extent += ROUND(sizeof(struct vmdk_grain_marker) + desc->blocks[block_index].size); } /* Add on size of grain directory */ extent += ROUND(gdsize) + sizeof(struct vmdk_marker); extent += 3 * BYTES_PER_SECTOR; /* footer marker, footer, EOS */ gt = calloc(1, gtsize); if (gt == NULL) { free(descriptor); free(header); return NULL; } gd = calloc(1, gdsize); if (gd == NULL) { free(gt); free(descriptor); free(header); return NULL; } /* Build the disk */ diskp = rawdisk = calloc(1, extent); if (rawdisk == NULL) { free(gd); free(gt); free(descriptor); free(header); return NULL; } /* Emit header and descriptor */ memcpy(diskp, header, sizeof(struct vmdk_sparse_extent_header)); diskp += sizeof(struct vmdk_sparse_extent_header); memcpy(diskp, descriptor, BYTES_PER_SECTOR); diskp += BYTES_PER_SECTOR; marker.num_sectors = ROUND(gtsize) / BYTES_PER_SECTOR; marker.size = 0; marker.type = 1; /* Grain table */ /* Emit blocks */ for (block_index = 0, gtbase = 0; block_index < desc->nblocks; block_index++) { if (desc->blocks[block_index].lba >= gtbase) { /* New grain table needed */ if (block_index > 0) { /* Record location in grain directory */ gd[desc->blocks[block_index - 1].lba / gtcoverage] = (diskp + sizeof(struct vmdk_marker) - rawdisk) / BYTES_PER_SECTOR; /* Emit current grain table */ memcpy(diskp, &marker, sizeof(struct vmdk_marker)); diskp += sizeof(struct vmdk_marker); memcpy(diskp, gt, gtsize); diskp += ROUND(gtsize); memset(gt, 0, gtsize); } /* Skip empty grain tables */ while (gtbase <= desc->blocks[block_index].lba) { gtbase += gtcoverage; } } /* Record block location in grain table */ gt[(desc->blocks[block_index].lba % gtcoverage) / gcoverage] = (diskp - rawdisk) / BYTES_PER_SECTOR; /* Emit block */ gmarker.lba = desc->blocks[block_index].lba / BYTES_PER_SECTOR; gmarker.size = desc->blocks[block_index].size; memcpy(diskp, &gmarker, sizeof(struct vmdk_grain_marker)); memset(diskp + sizeof(struct vmdk_grain_marker), desc->blocks[block_index].fill, desc->blocks[block_index].size); diskp += ROUND(sizeof(struct vmdk_grain_marker) + desc->blocks[block_index].size); } if (block_index > 0) { /* Record final grain table location in grain directory */ gd[desc->blocks[block_index - 1].lba / gtcoverage] = (diskp + sizeof(struct vmdk_marker) - rawdisk) / BYTES_PER_SECTOR; /* Emit final grain table */ memcpy(diskp, &marker, sizeof(struct vmdk_marker)); diskp += sizeof(struct vmdk_marker); memcpy(diskp, gt, gtsize); diskp += ROUND(gtsize); } /* Emit grain directory marker */ marker.num_sectors = ROUND(gdsize) / BYTES_PER_SECTOR; marker.size = 0; marker.type = 2; /* Grain directory */ memcpy(diskp, &marker, sizeof(struct vmdk_marker)); diskp += sizeof(struct vmdk_marker); /* Record grain directory location in footer */ header->gd_offset = (diskp - rawdisk) / BYTES_PER_SECTOR; /* Emit grain directory */ memcpy(diskp, gd, gdsize); diskp += ROUND(gdsize); /* Emit footer marker */ marker.num_sectors = 1; marker.size = 0; marker.type = 3; /* Footer */ memcpy(diskp, &marker, sizeof(struct vmdk_marker)); diskp += sizeof(struct vmdk_marker); /* Emit footer */ memcpy(diskp, header, sizeof(struct vmdk_sparse_extent_header)); diskp += sizeof(struct vmdk_sparse_extent_header); /* Emit EOS marker */ marker.num_sectors = 0; marker.size = 0; marker.type = 0; memcpy(diskp, &marker, sizeof(struct vmdk_marker)); diskp += sizeof(struct vmdk_marker); assert(diskp - rawdisk == extent); /* Clean up */ free(gd); free(gt); free(descriptor); free(header); *disk_size = extent; return rawdisk; }