Exemple #1
0
/*static*/ status_t
ELFLoader<Class>::Create(int fd, preloaded_image** _image)
{
	ImageType* image = (ImageType*)kernel_args_malloc(sizeof(ImageType));
	if (image == NULL)
		return B_NO_MEMORY;

	ssize_t length = read_pos(fd, 0, &image->elf_header, sizeof(EhdrType));
	if (length < (ssize_t)sizeof(EhdrType)) {
		kernel_args_free(image);
		return B_BAD_TYPE;
	}

	const EhdrType& elfHeader = image->elf_header;

	if (memcmp(elfHeader.e_ident, ELF_MAGIC, 4) != 0
		|| elfHeader.e_ident[4] != Class::kIdentClass
		|| elfHeader.e_phoff == 0
		|| !elfHeader.IsHostEndian()
		|| elfHeader.e_phentsize != sizeof(PhdrType)) {
		kernel_args_free(image);
		return B_BAD_TYPE;
	}

	image->elf_class = elfHeader.e_ident[EI_CLASS];

	*_image = image;
	return B_OK;
}
status_t
add_safe_mode_settings(char* settings)
{
	if (settings == NULL || settings[0] == '\0')
		return B_OK;

	size_t length = strlen(settings);
	char* buffer = (char*)kernel_args_malloc(length + 1);
	if (buffer == NULL)
		return B_NO_MEMORY;

	driver_settings_file* file = (driver_settings_file*)kernel_args_malloc(
		sizeof(driver_settings_file));
	if (file == NULL) {
		kernel_args_free(buffer);
		return B_NO_MEMORY;
	}

	strlcpy(file->name, B_SAFEMODE_DRIVER_SETTINGS, sizeof(file->name));
	memcpy(buffer, settings, length + 1);
	file->buffer = buffer;
	file->size = length;

	// add it to the list
	file->next = gKernelArgs.driver_settings;
	gKernelArgs.driver_settings = file;

	return B_OK;
}
Exemple #3
0
status_t
elf_load_image(Directory *directory, const char *path)
{
	preloaded_image *image;

	TRACE(("elf_load_image(directory = %p, \"%s\")\n", directory, path));

	int fd = open_from(directory, path, O_RDONLY);
	if (fd < 0)
		return fd;

	// check if this file has already been loaded

	struct stat stat;
	if (fstat(fd, &stat) < 0)
		return errno;

	image = gKernelArgs.preloaded_images;
	for (; image != NULL; image = image->next) {
		if (image->inode == stat.st_ino) {
			// file has already been loaded, no need to load it twice!
			close(fd);
			return B_OK;
		}
	}

	// we still need to load it, so do it

	image = (preloaded_image *)kernel_args_malloc(sizeof(preloaded_image));
	if (image == NULL) {
		close(fd);
		return B_NO_MEMORY;
	}

	status_t status = elf_load_image(fd, image);
	if (status == B_OK) {
		image->name = kernel_args_strdup(path);
		image->inode = stat.st_ino;

		// insert to kernel args
		image->next = gKernelArgs.preloaded_images;
		gKernelArgs.preloaded_images = image;
	} else
		kernel_args_free(image);

	close(fd);
	return status;
}
static status_t
load_driver_settings_file(Directory* directory, const char* name)
{
	int fd = open_from(directory, name, O_RDONLY);
	if (fd < 0)
		return fd;

	struct stat stat;
	if (fstat(fd, &stat) < 0)
		return errno;

	char* buffer = (char*)kernel_args_malloc(stat.st_size + 1);
	if (buffer == NULL)
		return B_NO_MEMORY;

	if (read(fd, buffer, stat.st_size) != stat.st_size)
		return B_IO_ERROR;

	driver_settings_file* file = (driver_settings_file*)kernel_args_malloc(
		sizeof(driver_settings_file));
	if (file == NULL) {
		kernel_args_free(buffer);
		return B_NO_MEMORY;
	}

	buffer[stat.st_size] = '\0';
		// null terminate the buffer

	strlcpy(file->name, name, sizeof(file->name));
	file->buffer = buffer;
	file->size = stat.st_size;

	// add it to the list
	file->next = gKernelArgs.driver_settings;
	gKernelArgs.driver_settings = file;

	return B_OK;
}
Exemple #5
0
/*static*/ status_t
ELFLoader<Class>::_LoadSymbolTable(int fd, ImageType* image)
{
	const EhdrType& elfHeader = image->elf_header;
	SymType* symbolTable = NULL;
	ShdrType* stringHeader = NULL;
	uint32 numSymbols = 0;
	char* stringTable;
	status_t status;

	// get section headers

	ssize_t size = elfHeader.e_shnum * elfHeader.e_shentsize;
	ShdrType* sectionHeaders = (ShdrType*)malloc(size);
	if (sectionHeaders == NULL) {
		dprintf("error allocating space for section headers\n");
		return B_NO_MEMORY;
	}

	ssize_t length = read_pos(fd, elfHeader.e_shoff, sectionHeaders, size);
	if (length < size) {
		TRACE(("error reading in program headers\n"));
		status = B_ERROR;
		goto error1;
	}

	// find symbol table in section headers

	for (int32 i = 0; i < elfHeader.e_shnum; i++) {
		if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
			stringHeader = &sectionHeaders[sectionHeaders[i].sh_link];

			if (stringHeader->sh_type != SHT_STRTAB) {
				TRACE(("doesn't link to string table\n"));
				status = B_BAD_DATA;
				goto error1;
			}

			// read in symbol table
			size = sectionHeaders[i].sh_size;
			symbolTable = (SymType*)kernel_args_malloc(size);
			if (symbolTable == NULL) {
				status = B_NO_MEMORY;
				goto error1;
			}

			length = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable,
				size);
			if (length < size) {
				TRACE(("error reading in symbol table\n"));
				status = B_ERROR;
				goto error1;
			}

			numSymbols = size / sizeof(SymType);
			break;
		}
	}

	if (symbolTable == NULL) {
		TRACE(("no symbol table\n"));
		status = B_BAD_VALUE;
		goto error1;
	}

	// read in string table

	size = stringHeader->sh_size;
	stringTable = (char*)kernel_args_malloc(size);
	if (stringTable == NULL) {
		status = B_NO_MEMORY;
		goto error2;
	}

	length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
	if (length < size) {
		TRACE(("error reading in string table\n"));
		status = B_ERROR;
		goto error3;
	}

	TRACE(("loaded %ld debug symbols\n", numSymbols));

	// insert tables into image
	image->debug_symbols = symbolTable;
	image->num_debug_symbols = numSymbols;
	image->debug_string_table = stringTable;
	image->debug_string_table_size = size;

	free(sectionHeaders);
	return B_OK;

error3:
	kernel_args_free(stringTable);
error2:
	kernel_args_free(symbolTable);
error1:
	free(sectionHeaders);

	return status;
}
Exemple #6
0
/*static*/ status_t
ELFLoader<Class>::Load(int fd, preloaded_image* _image)
{
	size_t totalSize;
	ssize_t length;
	status_t status;
	void* mappedRegion = NULL;

	ImageType* image = static_cast<ImageType*>(_image);
	const EhdrType& elfHeader = image->elf_header;

	ssize_t size = elfHeader.e_phnum * elfHeader.e_phentsize;
	PhdrType* programHeaders = (PhdrType*)malloc(size);
	if (programHeaders == NULL) {
		dprintf("error allocating space for program headers\n");
		status = B_NO_MEMORY;
		goto error1;
	}

	length = read_pos(fd, elfHeader.e_phoff, programHeaders, size);
	if (length < size) {
		TRACE(("error reading in program headers\n"));
		status = B_ERROR;
		goto error1;
	}

	// create an area large enough to hold the image

	image->data_region.size = 0;
	image->text_region.size = 0;

	for (int32 i = 0; i < elfHeader.e_phnum; i++) {
		PhdrType& header = programHeaders[i];

		switch (header.p_type) {
			case PT_LOAD:
				break;
			case PT_DYNAMIC:
				image->dynamic_section.start = header.p_vaddr;
				image->dynamic_section.size = header.p_memsz;
				continue;
			case PT_INTERP:
			case PT_PHDR:
			case PT_ARM_UNWIND:
				// known but unused type
				continue;
			default:
				dprintf("unhandled pheader type 0x%" B_PRIx32 "\n", header.p_type);
				continue;
		}

		RegionType* region;
		if (header.IsReadWrite()) {
			if (image->data_region.size != 0) {
				dprintf("elf: rw already handled!\n");
				continue;
			}
			region = &image->data_region;
		} else if (header.IsExecutable()) {
			if (image->text_region.size != 0) {
				dprintf("elf: ro already handled!\n");
				continue;
			}
			region = &image->text_region;
		} else
			continue;

		region->start = ROUNDDOWN(header.p_vaddr, B_PAGE_SIZE);
		region->size = ROUNDUP(header.p_memsz + (header.p_vaddr % B_PAGE_SIZE),
			B_PAGE_SIZE);
		region->delta = -region->start;

		TRACE(("segment %ld: start = 0x%llx, size = %llu, delta = %llx\n", i,
			(uint64)region->start, (uint64)region->size,
			(int64)(AddrType)region->delta));
	}

	// found both, text and data?
	if (image->data_region.size == 0 || image->text_region.size == 0) {
		dprintf("Couldn't find both text and data segment!\n");
		status = B_BAD_DATA;
		goto error1;
	}

	// get the segment order
	RegionType* firstRegion;
	RegionType* secondRegion;
	if (image->text_region.start < image->data_region.start) {
		firstRegion = &image->text_region;
		secondRegion = &image->data_region;
	} else {
		firstRegion = &image->data_region;
		secondRegion = &image->text_region;
	}

	// The kernel and the modules are relocatable, thus AllocateRegion()
	// can automatically allocate an address, but shall prefer the specified
	// base address.
	totalSize = secondRegion->start + secondRegion->size - firstRegion->start;
	if (Class::AllocateRegion(&firstRegion->start, totalSize,
			B_READ_AREA | B_WRITE_AREA, &mappedRegion) != B_OK) {
		status = B_NO_MEMORY;
		goto error1;
	}

	// initialize the region pointers to the allocated region
	secondRegion->start += firstRegion->start + firstRegion->delta;

	image->data_region.delta += image->data_region.start;
	image->text_region.delta += image->text_region.start;

	TRACE(("text: start 0x%llx, size 0x%llx, delta 0x%llx\n",
		(uint64)image->text_region.start, (uint64)image->text_region.size,
		(int64)(AddrType)image->text_region.delta));
	TRACE(("data: start 0x%llx, size 0x%llx, delta 0x%llx\n",
		(uint64)image->data_region.start, (uint64)image->data_region.size,
		(int64)(AddrType)image->data_region.delta));

	// load program data

	for (int32 i = 0; i < elfHeader.e_phnum; i++) {
		PhdrType& header = programHeaders[i];

		if (header.p_type != PT_LOAD)
			continue;

		RegionType* region;
		if (header.IsReadWrite())
			region = &image->data_region;
		else if (header.IsExecutable())
			region = &image->text_region;
		else
			continue;

		TRACE(("load segment %ld (%llu bytes) mapped at %p...\n", i,
			(uint64)header.p_filesz, Class::Map(region->start)));

		length = read_pos(fd, header.p_offset,
			Class::Map(region->start + (header.p_vaddr % B_PAGE_SIZE)),
			header.p_filesz);
		if (length < (ssize_t)header.p_filesz) {
			status = B_BAD_DATA;
			dprintf("error reading in seg %" B_PRId32 "\n", i);
			goto error2;
		}

		// Clear anything above the file size (that may also contain the BSS
		// area)

		uint32 offset = (header.p_vaddr % B_PAGE_SIZE) + header.p_filesz;
		if (offset < region->size)
			memset(Class::Map(region->start + offset), 0, region->size - offset);
	}

	// offset dynamic section, and program entry addresses by the delta of the
	// regions
	image->dynamic_section.start += image->text_region.delta;
	image->elf_header.e_entry += image->text_region.delta;

	image->num_debug_symbols = 0;
	image->debug_symbols = NULL;
	image->debug_string_table = NULL;

	if (sLoadElfSymbols)
		_LoadSymbolTable(fd, image);

	free(programHeaders);

	return B_OK;

error2:
	if (mappedRegion != NULL)
		platform_free_region(mappedRegion, totalSize);
error1:
	free(programHeaders);
	kernel_args_free(image);

	return status;
}
extern "C" status_t
video_display_splash(addr_t frameBuffer)
{
	if (!gKernelArgs.frame_buffer.enabled)
		return B_NO_INIT;

	// clear the video memory
	memset((void*)frameBuffer, 0,
		gKernelArgs.frame_buffer.physical_buffer.size);

	uint8* uncompressedLogo = NULL;
	unsigned int uncompressedSize = kSplashLogoWidth * kSplashLogoHeight;
	switch (gKernelArgs.frame_buffer.depth) {
		case 8:
			platform_set_palette(k8BitPalette);
			uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
			if (uncompressedLogo == NULL)
				return B_NO_MEMORY;

			uncompress(kSplashLogo8BitCompressedImage,
				sizeof(kSplashLogo8BitCompressedImage), uncompressedLogo,
				uncompressedSize);
		break;
		default: // 24 bits is assumed here
			uncompressedSize *= 3;
			uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
			if (uncompressedLogo == NULL)
				return B_NO_MEMORY;

			uncompress(kSplashLogo24BitCompressedImage,
				sizeof(kSplashLogo24BitCompressedImage), uncompressedLogo,
				uncompressedSize);
		break;
	}

	// TODO: support 4-bit indexed version of the images!

	// render splash logo
	uint16 iconsHalfHeight = kSplashIconsHeight / 2;

	int width = min_c(kSplashLogoWidth, gKernelArgs.frame_buffer.width);
	int height = min_c(kSplashLogoHeight + iconsHalfHeight,
		gKernelArgs.frame_buffer.height);
	int placementX = max_c(0, min_c(100, kSplashLogoPlacementX));
	int placementY = max_c(0, min_c(100, kSplashLogoPlacementY));

	int x = (gKernelArgs.frame_buffer.width - width) * placementX / 100;
	int y = (gKernelArgs.frame_buffer.height - height) * placementY / 100;

	height = min_c(kSplashLogoHeight, gKernelArgs.frame_buffer.height);
	switch (gKernelArgs.frame_buffer.depth) {
		case 8:
			break;
	}
	video_blit_image(frameBuffer, uncompressedLogo, width, height,
		kSplashLogoWidth, x, y);

	kernel_args_free(uncompressedLogo);

	const uint8* lowerHalfIconImage;
	uncompressedSize = kSplashIconsWidth * kSplashIconsHeight;
	switch (gKernelArgs.frame_buffer.depth) {
		case 8:
			// pointer into the lower half of the icons image data
			gKernelArgs.boot_splash
				= (uint8*)kernel_args_malloc(uncompressedSize);
			if (gKernelArgs.boot_splash == NULL)
				return B_NO_MEMORY;
			uncompress(kSplashIcons8BitCompressedImage,
				sizeof(kSplashIcons8BitCompressedImage),
				gKernelArgs.boot_splash, uncompressedSize);
			lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash
				+ (kSplashIconsWidth * iconsHalfHeight);
		break;
		default:	// 24bits is assumed here
			uncompressedSize *= 3;
			// pointer into the lower half of the icons image data
			gKernelArgs.boot_splash
				= (uint8*)kernel_args_malloc(uncompressedSize);
			if (gKernelArgs.boot_splash == NULL)
				return B_NO_MEMORY;
			uncompress(kSplashIcons24BitCompressedImage,
				sizeof(kSplashIcons24BitCompressedImage),
				gKernelArgs.boot_splash, uncompressedSize);
			lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash
				+ (kSplashIconsWidth * iconsHalfHeight) * 3;
		break;
	}

	// render initial (grayed out) icons
	// the grayed out version is the lower half of the icons image

	width = min_c(kSplashIconsWidth, gKernelArgs.frame_buffer.width);
	height = min_c(kSplashLogoHeight + iconsHalfHeight,
		gKernelArgs.frame_buffer.height);
	placementX = max_c(0, min_c(100, kSplashIconsPlacementX));
	placementY = max_c(0, min_c(100, kSplashIconsPlacementY));

	x = (gKernelArgs.frame_buffer.width - width) * placementX / 100;
	y = kSplashLogoHeight + (gKernelArgs.frame_buffer.height - height)
		* placementY / 100;

	height = min_c(iconsHalfHeight, gKernelArgs.frame_buffer.height);
	video_blit_image(frameBuffer, lowerHalfIconImage, width, height,
		kSplashIconsWidth, x, y);
	return B_OK;
}