Beispiel #1
0
/**
 * Initializes memory mirror.
 *
 * Memory mirror allocates all available ram to specific range address.
 * If 1GB paging is supported, 1GB paging is used, otherwise only 4KB
 * paging is used, which means much more physical ram is used.
 */
void initialize_memory_mirror() {
    section_info_t* head = frame_pool;
    frame_pool = NULL;
    bool first_set = false;
    if (is_1GB_paging_supported() != 0) {
        for (puint_t start=0; start < maxram; start+=1<<30) {
            puint_t vaddress = start + ADDRESS_OFFSET(RESERVED_KBLOCK_RAM_MAPPINGS);
            v_address_t va;
            memcpy(&va, &vaddress, 8);

            puint_t* pml4 = (puint_t*)ALIGN(physical_to_virtual(get_active_page()));
            if (!PRESENT(pml4[va.pml])) {
                pdpt_t pdpt;
                memset(&pdpt, 0, sizeof(pdpt_t));
                pdpt.number = get_free_frame();
                pdpt.flaggable.present = 1;
                pdpt.flaggable.us = 0;
                pdpt.flaggable.rw = 1;
                pml4[va.pml] = pdpt.number;
                memset((void*)physical_to_virtual(ALIGN(pdpt.number)), 0, 0x1000);
            }

            puint_t* pdpt = (puint_t*)ALIGN(physical_to_virtual(pml4[va.pml]));

            page_directory1GB_t dir;
            memset(&dir, 0, sizeof(page_directory1GB_t));
            dir.number = start;
            dir.flaggable.present = 1;
            dir.flaggable.ps = 1;
            dir.flaggable.rw = 1;
            pdpt[va.directory_ptr] = dir.number;

            if (!first_set) {
                first_set = true;
                frame_pool = head;
            }
        }
    } else {
        for (puint_t start=0; start < maxram; start+=0x1000) {
            puint_t kend = kernel_tmp_heap_start - 0xFFFFFFFF80000000 + 0x40000;
            if (kend+0x4000 >= tmp_heap && !first_set) {
                first_set = true;
                frame_pool = head;
            }

            puint_t vaddress = start + ADDRESS_OFFSET(RESERVED_KBLOCK_RAM_MAPPINGS);
            puint_t* paddress = get_page(vaddress, get_active_page(), true);
            page_t page;
            memset(&page, 0, sizeof(page_t));
            page.address = start;
            page.flaggable.present = 1;
            page.flaggable.rw = 1;
            page.flaggable.us = 0;
            *paddress = page.address;
        }

    }
}
Beispiel #2
0
/**
 * Returns address + physical identity map offset
 */
uintptr_t physical_to_virtual(puint_t paddress) {
    if (!__mem_mirror_present)
        return paddress;
    if (paddress == 0)
        return 0;
    return paddress + ADDRESS_OFFSET(RESERVED_KBLOCK_RAM_MAPPINGS);
}
Beispiel #3
0
/**
 * Computes virtual to physical mapping.
 *
 * Checks for page hierarchy and determines what physical address will be.
 * If page structures are missing on the way to decode, physical address cannot
 * be found and this valid will contain 0, otherwise valid will contain 1
 *
 * 1GB page sector (ram identity map) behaves slightly different, because it
 * needs different v_address_t type.
 */
ruint_t virtual_to_physical(uintptr_t vaddress, uintptr_t cr3, uint8_t* valid) {
    *valid = 1;
    v_address_t va;
    memcpy(&va, &vaddress, 8);

    puint_t* address = (puint_t*)ALIGN(physical_to_virtual(cr3));
    address = (puint_t*)ALIGN(physical_to_virtual(address[va.pml]));

    if (!PRESENT(address)) {
        *valid = 0;
        return 0;
    }

    if (vaddress > ADDRESS_OFFSET(RESERVED_KBLOCK_RAM_MAPPINGS) &&
                vaddress < ADDRESS_OFFSET((RESERVED_KBLOCK_RAM_MAPPINGS+1)) &&
                is_1GB_paging_supported()) {
        v_address1GB_t va = *((v_address1GB_t*) &vaddress);
        page_directory1GB_t pd1gb;
        pd1gb.number = (uint64_t) address;
        return pd1gb.flaggable.address + va.offset;
    }

    address = (puint_t*)ALIGN(physical_to_virtual(address[va.directory_ptr]));

    if (!PRESENT(address)) {
        *valid = 0;
        return 0;
    }

    address = (puint_t*)ALIGN(physical_to_virtual(address[va.directory]));

    if (!PRESENT(address)) {
        *valid = 0;
        return 0;
    }

    if (!PRESENT(*address)) {
        *valid = 0;
        return 0;
    }

    puint_t physadd = *address;
    return ALIGN(physadd) + va.offset;
}
Beispiel #4
0
static status_t
GetEdidFromBIOS(edid1_raw& edidRaw)
{
	// Get the EDID info from the video BIOS, and return B_OK if successful.

#define ADDRESS_SEGMENT(address) ((addr_t)(address) >> 4)
#define ADDRESS_OFFSET(address) ((addr_t)(address) & 0xf)

	vm86_state vmState;

	status_t status = vm86_prepare(&vmState, 0x2000);
	if (status != B_OK) {
		TRACE("GetEdidFromBIOS(); vm86_prepare() failed, status: 0x%lx\n",
			status);
		return status;
	}

	vmState.regs.eax = 0x4f15;
	vmState.regs.ebx = 0;		// 0 = report DDC service
	vmState.regs.ecx = 0;
	vmState.regs.es = 0;
	vmState.regs.edi = 0;

	status = vm86_do_int(&vmState, 0x10);
	if (status == B_OK) {
		// AH contains the error code, and AL determines wether or not the
		// function is supported.
		if (vmState.regs.eax != 0x4f)
			status = B_NOT_SUPPORTED;

		// Test if DDC is supported by the monitor.
		if ((vmState.regs.ebx & 3) == 0)
			status = B_NOT_SUPPORTED;
	}

	if (status == B_OK) {
		// According to the author of the vm86 functions, the address of any
		// object to receive data must be >= 0x1000 and within the ram size
		// specified in the second argument of the vm86_prepare() call above.
		// Thus, the address of the struct to receive the EDID info is set to
		// 0x1000.

		edid1_raw* edid = (edid1_raw*)0x1000;

		vmState.regs.eax = 0x4f15;
		vmState.regs.ebx = 1;		// 1 = read EDID
		vmState.regs.ecx = 0;
		vmState.regs.edx = 0;
		vmState.regs.es  = ADDRESS_SEGMENT(edid);
		vmState.regs.edi = ADDRESS_OFFSET(edid);

		status = vm86_do_int(&vmState, 0x10);
		if (status == B_OK) {
			if (vmState.regs.eax != 0x4f) {
				status = B_NOT_SUPPORTED;
			} else {
				// Copy the EDID info to the caller's location, and compute the
				// checksum of the EDID info while copying.

				uint8 sum = 0;
				uint8 allOr = 0;
				uint8* dest = (uint8*)&edidRaw;
				uint8* src = (uint8*)edid;

				for (uint32 j = 0; j < sizeof(edidRaw); j++) {
					sum += *src;
					allOr |= *src;
					*dest++ = *src++;
				}

				if (allOr == 0) {
					TRACE("GetEdidFromBIOS(); EDID info contains only zeros\n");
					status = B_ERROR;
				} else if (sum != 0) {
					TRACE("GetEdidFromBIOS(); Checksum error in EDID info\n");
					status = B_ERROR;
				}
			}
		}
	}

	vm86_cleanup(&vmState);

	return status;
}
static status_t
GetEdidFromBIOS(edid1_raw& edidRaw)
{
	// Get the EDID info from the video BIOS, and return B_OK if successful.

#define ADDRESS_SEGMENT(address) ((addr_t)(address) >> 4)
#define ADDRESS_OFFSET(address) ((addr_t)(address) & 0xf)

	bios_module_info* biosModule;
	status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule);
	if (status != B_OK) {
		TRACE("GetEdidFromBIOS(): failed to get BIOS module: 0x%" B_PRIx32 "\n",
			status);
		return status;
	}

	bios_state* state;
	status = biosModule->prepare(&state);
	if (status != B_OK) {
		TRACE("GetEdidFromBIOS(): bios_prepare() failed: 0x%" B_PRIx32 "\n",
			status);
		put_module(B_BIOS_MODULE_NAME);
		return status;
	}

	bios_regs regs = {};
	regs.eax = 0x4f15;
	regs.ebx = 0;			// 0 = report DDC service
	regs.ecx = 0;
	regs.es = 0;
	regs.edi = 0;

	status = biosModule->interrupt(state, 0x10, &regs);
	if (status == B_OK) {
		// AH contains the error code, and AL determines whether or not the
		// function is supported.
		if (regs.eax != 0x4f)
			status = B_NOT_SUPPORTED;

		// Test if DDC is supported by the monitor.
		if ((regs.ebx & 3) == 0)
			status = B_NOT_SUPPORTED;
	}

	if (status == B_OK) {
		edid1_raw* edid = (edid1_raw*)biosModule->allocate_mem(state,
			sizeof(edid1_raw));
		if (edid == NULL) {
			status = B_NO_MEMORY;
			goto out;
		}

		regs.eax = 0x4f15;
		regs.ebx = 1;		// 1 = read EDID
		regs.ecx = 0;
		regs.edx = 0;
		regs.es  = ADDRESS_SEGMENT(edid);
		regs.edi = ADDRESS_OFFSET(edid);

		status = biosModule->interrupt(state, 0x10, &regs);
		if (status == B_OK) {
			if (regs.eax != 0x4f) {
				status = B_NOT_SUPPORTED;
			} else {
				// Copy the EDID info to the caller's location, and compute the
				// checksum of the EDID info while copying.

				uint8 sum = 0;
				uint8 allOr = 0;
				uint8* dest = (uint8*)&edidRaw;
				uint8* src = (uint8*)edid;

				for (uint32 j = 0; j < sizeof(edidRaw); j++) {
					sum += *src;
					allOr |= *src;
					*dest++ = *src++;
				}

				if (allOr == 0) {
					TRACE("GetEdidFromBIOS(); EDID info contains only zeros\n");
					status = B_ERROR;
				} else if (sum != 0) {
					TRACE("GetEdidFromBIOS(); Checksum error in EDID info\n");
					status = B_ERROR;
				}
			}
		}
	}

out:
	biosModule->finish(state);
	put_module(B_BIOS_MODULE_NAME);

	TRACE("GetEdidFromBIOS() status: 0x%" B_PRIx32 "\n", status);
	return status;
}