Ejemplo n.º 1
0
/* 
 * 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;
}
Ejemplo n.º 2
0
/* 
 * 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;
}
Ejemplo n.º 3
0
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;
}