示例#1
0
文件: vbe.c 项目: jiangxilong/kiwi
/** Set the display mode.
 * @param _dev		Device to set mode of.
 * @param mode		Mode structure for mode to set.
 * @return		Status code describing result of the operation. */
static status_t vbe_display_set_mode(display_device_t *_device, display_mode_t *mode) {
	bios_regs_t regs;

	if(mode) {
		/* Check if anything needs to be done. */
		bios_regs_init(&regs);
		regs.eax = VBE_FUNCTION_GET_MODE;
		bios_interrupt(0x10, &regs);
		if((regs.eax & 0xFF00) != 0) {
			kprintf(LOG_DEBUG, "vbe: call failed with code 0x%x\n", regs.eax & 0xFFFF);
			return STATUS_DEVICE_ERROR;
		}
		if((regs.ebx & ~((1<<14) | (1<<15))) == mode->id) {
			return STATUS_SUCCESS;
		}

		kprintf(LOG_DEBUG, "vbe: switching to mode 0x%" PRIx32 " (mode: %p)\n", mode->id, mode);
	}

	/* Set bit 14 in the mode register to use linear framebuffer model. */
	bios_regs_init(&regs);
	regs.eax = VBE_FUNCTION_SET_MODE;
	regs.ebx = (mode) ? (mode->id | (1<<14)) : 3;
	bios_interrupt(0x10, &regs);
	if((regs.eax & 0xFF00) != 0) {
		kprintf(LOG_DEBUG, "vbe: call failed with code 0x%x\n", regs.eax & 0xFFFF);
		return STATUS_DEVICE_ERROR;
	}

	return STATUS_SUCCESS;
}
示例#2
0
文件: pxe.c 项目: gil0mendes/Initium
/**
 * Get the PXE entry point address.
 *
 * @return              Whether the entry point could be found.
 */
static bool get_entry_point(void) {
  bios_regs_t regs;
  pxenv_t *pxenv;
  pxe_t *pxe;

  /* Use the PXE installation check function. */
  bios_regs_init(&regs);
  regs.eax = INT1A_PXE_INSTALL_CHECK;
  bios_call(0x1a, &regs);
  if (regs.eax != INT1A_PXE_INSTALL_CHECK_RET || regs.eflags & X86_FLAGS_CF) {
    dprintf("pxe: loaded via PXE but PXE not available\n");
    return false;
  }

  /* Get the PXENV+ structure. */
  pxenv = (pxenv_t *)segoff_to_linear((regs.es << 16) | regs.bx);
  if (memcmp(pxenv->signature, PXENV_SIGNATURE, sizeof(pxenv->signature)) != 0) {
    boot_error("PXENV+ structure has incorrect signature");
  } else if (!checksum_range(pxenv, pxenv->length)) {
    boot_error("PXENV+ structure is corrupt");
  }

  /* Get the !PXE structure. */
  pxe = (pxe_t *)segoff_to_linear(pxenv->pxe_ptr);
  if (memcmp(pxe->signature, PXE_SIGNATURE, sizeof(pxe->signature)) != 0) {
    boot_error("!PXE structure has incorrect signature");
  } else if (!checksum_range(pxe, pxe->length)) {
    boot_error("!PXE structure is corrupt");
  }

  pxe_entry_point = pxe->entry_point_16;
  return true;
}
示例#3
0
文件: vbe.c 项目: jiangxilong/kiwi
/** Initialisation function for the VBE driver.
 * @return		Status code describing result of the operation. */
static status_t vbe_init(void) {
	phys_ptr_t mem_phys = ~((phys_ptr_t)0);
	size_t count = 0, i, mem_size = 0;
	vbe_mode_info_t *minfo = NULL;
	display_mode_t *modes = NULL;
	vbe_info_t *info = NULL;
	uint16_t *location;
	bios_regs_t regs;
	status_t ret;

	/* Detect VBE presence by trying to get controller information. */
	info = bios_mem_alloc(sizeof(vbe_info_t), MM_WAIT);
	strncpy(info->vbe_signature, "VBE2", 4);
	bios_regs_init(&regs);
	regs.eax = VBE_FUNCTION_CONTROLLER_INFO;
	regs.edi = bios_mem_virt2phys(info);
	bios_interrupt(0x10, &regs);
	if((regs.eax & 0x00FF) != 0x4F) {
		kprintf(LOG_DEBUG, "vbe: VBE is not supported!\n");
		ret = STATUS_NOT_SUPPORTED;
		goto out;
	} else if((regs.eax & 0xFF00) != 0) {
		kprintf(LOG_DEBUG, "vbe: call failed with code 0x%x\n", regs.eax & 0xFFFF);
		ret = STATUS_DEVICE_ERROR;
		goto out;
	}

	kprintf(LOG_NOTICE, "vbe: vbe presence was detected:\n");
	kprintf(LOG_NOTICE, " signature:    %s\n", info->vbe_signature);
	kprintf(LOG_NOTICE, " version:      0x%" PRIx16 "\n", info->vbe_version);
	kprintf(LOG_NOTICE, " capabilities: 0x%" PRIx32 "\n", info->capabilities);
	kprintf(LOG_NOTICE, " mode pointer: 0x%" PRIx32 "\n", info->video_mode_ptr);
	kprintf(LOG_NOTICE, " total memory: %" PRIu16 "KB\n", info->total_memory * 64);
	if(info->vbe_version >= 0x0200) {
		kprintf(LOG_NOTICE, " OEM revision: 0x%" PRIx16 "\n", info->oem_software_rev);
	}
	mem_size = (info->total_memory * 64) * 1024;

	location = bios_mem_phys2virt(SEGOFF2LIN(info->video_mode_ptr));
	if(!location) {
		ret = STATUS_DEVICE_ERROR;
		goto out;
	}

	/* Allocate a region to store the mode information structure in. */
	minfo = bios_mem_alloc(sizeof(vbe_mode_info_t), MM_WAIT);

	/* Iterate through all the modes available. An ID of 0xFFFF indicates
	 * the end of the mode list. */
	for(i = 0; location[i] != 0xFFFF; i++) {
		/* Get information on the mode. */
		bios_regs_init(&regs);
		regs.eax = VBE_FUNCTION_MODE_INFO;
		regs.ecx = location[i];
		regs.edi = bios_mem_virt2phys(minfo);
		bios_interrupt(0x10, &regs);
		if((regs.eax & 0xFF00) != 0) {
			kprintf(LOG_DEBUG, "vbe: call failed with code 0x%x\n", regs.eax & 0xFFFF);
			ret = STATUS_DEVICE_ERROR;
			goto out;
		}

		/* Check if the mode is suitable. */
		if(minfo->memory_model != 4 && minfo->memory_model != 6) {
			/* Not packed-pixel or direct colour. */
			continue;
		} else if(minfo->phys_base_ptr == 0) {
			/* Borked. */
			continue;
		} else if((minfo->mode_attributes & (1<<0)) == 0) {
			/* Not supported. */
			continue;
		} else if((minfo->mode_attributes & (1<<3)) == 0) {
			/* Not colour. */
			continue;
		} else if((minfo->mode_attributes & (1<<4)) == 0) {
			/* Not a graphics mode. */
			continue;
		} else if((minfo->mode_attributes & (1<<7)) == 0) {
			/* Not usable in linear mode. */
			continue;
		} else if(minfo->bits_per_pixel != 8 && minfo->bits_per_pixel != 16 &&
		          minfo->bits_per_pixel != 24 && minfo->bits_per_pixel != 32) {
			continue;
		}

		/* Add the mode to the mode array. To begin with, set offset to
		 * the full physical address. */
		modes = krealloc(modes, sizeof(display_mode_t) * (count + 1), MM_WAIT);
		modes[count].id = location[i];
		modes[count].width = minfo->x_resolution;
		modes[count].height = minfo->y_resolution;
		modes[count].format = depth_to_format(minfo->bits_per_pixel);
		modes[count].offset = minfo->phys_base_ptr;
		count++;

		/* Try to guess the memory address. */
		if(minfo->phys_base_ptr < mem_phys) {
			mem_phys = minfo->phys_base_ptr;
		}
	}

	/* Now fix up mode offsets. */
	for(i = 0; i < count; i++) {
		modes[i].offset = modes[i].offset - mem_phys;
	}

	/* Set the cache mode on the framebuffer to WC. */
	phys_set_memory_type(mem_phys, ROUND_UP(mem_size, PAGE_SIZE), MEMORY_TYPE_WC);

	/* Add the display device. */
	ret = display_device_create(NULL, NULL, &vbe_display_ops, NULL, modes, count,
	                            mem_phys, mem_size, &vbe_display_device);
	if(ret != STATUS_SUCCESS) {
		return ret;
	}
out:
	if(minfo) {
		bios_mem_free(minfo, sizeof(vbe_mode_info_t));
	}
	if(info) {
		bios_mem_free(info, sizeof(vbe_info_t));
	}
	return ret;
}