Esempio n. 1
0
VOID
ReserveMemory(
    ULONG_PTR BaseAddress,
    SIZE_T Size,
    TYPE_OF_MEMORY MemoryType,
    PCHAR Usage)
{
    ULONG_PTR BasePage, PageCount;
    ULONG i;

    BasePage = BaseAddress / PAGE_SIZE;
    PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, Size);

    for (i = 0; i < PcMapCount; i++)
    {
        /* Check for conflicting descriptor */
        if ((PcMemoryMap[i].BasePage < BasePage + PageCount) &&
            (PcMemoryMap[i].BasePage + PcMemoryMap[i].PageCount > BasePage))
        {
            /* Check if the memory is free */
            if (PcMemoryMap[i].MemoryType != LoaderFree)
            {
                FrLdrBugCheckWithMessage(
                    MEMORY_INIT_FAILURE,
                    __FILE__,
                    __LINE__,
                    "Failed to reserve memory in the range 0x%Ix - 0x%Ix for %s",
                    BaseAddress,
                    Size,
                    Usage);
            }
        }
    }

    /* Add the memory descriptor */
    PcMapCount = AddMemoryDescriptor(PcMemoryMap,
                                     MAX_BIOS_DESCRIPTORS,
                                     BasePage,
                                     PageCount,
                                     MemoryType);
}
Esempio n. 2
0
static
ULONG
PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
{
    REGS Regs;
    ULONG MapCount = 0;
    ULONGLONG RealBaseAddress, RealSize;
    TYPE_OF_MEMORY MemoryType;
    ULONG Size;
    ASSERT(PcBiosMapCount == 0);

    TRACE("GetBiosMemoryMap()\n");

    /* Make sure the usable memory is large enough. To do this we check the 16
       bit value at address 0x413 inside the BDA, which gives us the usable size
       in KB */
    Size = (*(PUSHORT)(ULONG_PTR)0x413) * 1024;
    if (Size < MEMORY_MARGIN)
    {
        FrLdrBugCheckWithMessage(
            MEMORY_INIT_FAILURE,
            __FILE__,
            __LINE__,
            "The BIOS reported a usable memory range up to 0x%x, which is too small!\n\n"
            "If you see this, please report to the ReactOS team!",
            Size);
    }

    /* Get the address of the Extended BIOS Data Area (EBDA).
     * Int 15h, AH=C1h
     * SYSTEM - RETURN EXTENDED-BIOS DATA-AREA SEGMENT ADDRESS (PS)
     *
     * Return:
     * CF set on error
     * CF clear if successful
     * ES = segment of data area
     */
    Regs.x.eax = 0x0000C100;
    Int386(0x15, &Regs, &Regs);

    /* If the function fails, there is no EBDA */
    if (INT386_SUCCESS(Regs))
    {
        /* Check if this is high enough */
        ULONG EbdaBase = (ULONG)Regs.w.es << 4;
        if (EbdaBase < MEMORY_MARGIN)
        {
            FrLdrBugCheckWithMessage(
                MEMORY_INIT_FAILURE,
                __FILE__,
                __LINE__,
                "The location of your EBDA is 0x%lx, which is too low!\n\n"
                "If you see this, please report to the ReactOS team!",
                EbdaBase);
        }

        /* Calculate the (max) size of the EBDA */
        Size = 0xA0000 - EbdaBase;

        /* Add the descriptor */
        MapCount = AddMemoryDescriptor(PcMemoryMap,
                                       MAX_BIOS_DESCRIPTORS,
                                       (EbdaBase / MM_PAGE_SIZE),
                                       (Size / MM_PAGE_SIZE),
                                       LoaderFirmwarePermanent);
    }

    /* Int 15h AX=E820h
     * Newer BIOSes - GET SYSTEM MEMORY MAP
     *
     * AX = E820h
     * EAX = 0000E820h
     * EDX = 534D4150h ('SMAP')
     * EBX = continuation value or 00000000h to start at beginning of map
     * ECX = size of buffer for result, in bytes (should be >= 20 bytes)
     * ES:DI -> buffer for result
     * Return:
     * CF clear if successful
     * EAX = 534D4150h ('SMAP')
     * ES:DI buffer filled
     * EBX = next offset from which to copy or 00000000h if all done
     * ECX = actual length returned in bytes
     * CF set on error
     * AH = error code (86h)
     */
    Regs.x.ebx = 0x00000000;

    while (PcBiosMapCount < MAX_BIOS_DESCRIPTORS)
    {
        /* Setup the registers for the BIOS call */
        Regs.x.eax = 0x0000E820;
        Regs.x.edx = 0x534D4150; /* ('SMAP') */
        /* Regs.x.ebx = 0x00000001;  Continuation value already set */
        Regs.x.ecx = sizeof(BIOS_MEMORY_MAP);
        Regs.w.es = BIOSCALLBUFSEGMENT;
        Regs.w.di = BIOSCALLBUFOFFSET;
        Int386(0x15, &Regs, &Regs);

        TRACE("Memory Map Entry %d\n", PcBiosMapCount);
        TRACE("Int15h AX=E820h\n");
        TRACE("EAX = 0x%x\n", Regs.x.eax);
        TRACE("EBX = 0x%x\n", Regs.x.ebx);
        TRACE("ECX = 0x%x\n", Regs.x.ecx);
        TRACE("CF set = %s\n", (Regs.x.eflags & EFLAGS_CF) ? "TRUE" : "FALSE");

        /* If the BIOS didn't return 'SMAP' in EAX then
         * it doesn't support this call. If CF is set, we're done */
        if (Regs.x.eax != 0x534D4150 || !INT386_SUCCESS(Regs))
        {
            break;
        }

        /* Copy data to global buffer */
        RtlCopyMemory(&PcBiosMemoryMap[PcBiosMapCount], (PVOID)BIOSCALLBUFFER, Regs.x.ecx);

        TRACE("BaseAddress: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].BaseAddress);
        TRACE("Length: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].Length);
        TRACE("Type: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Type);
        TRACE("Reserved: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Reserved);
        TRACE("\n");

        /* Check if this is free memory */
        if (PcBiosMemoryMap[PcBiosMapCount].Type == BiosMemoryUsable)
        {
            MemoryType = LoaderFree;

            /* Align up base of memory area */
            RealBaseAddress = PcBiosMemoryMap[PcBiosMapCount].BaseAddress & ~(MM_PAGE_SIZE - 1ULL);

            /* Calculate the length after aligning the base */
            RealSize = PcBiosMemoryMap[PcBiosMapCount].BaseAddress +
                       PcBiosMemoryMap[PcBiosMapCount].Length - RealBaseAddress;
            RealSize = (RealSize + MM_PAGE_SIZE - 1) & ~(MM_PAGE_SIZE - 1ULL);
        }
        else
        {
            if (PcBiosMemoryMap[PcBiosMapCount].Type == BiosMemoryReserved)
                MemoryType = LoaderFirmwarePermanent;
            else
                MemoryType = LoaderSpecialMemory;

            /* Align down base of memory area */
            RealBaseAddress = PcBiosMemoryMap[PcBiosMapCount].BaseAddress & ~(MM_PAGE_SIZE - 1ULL);
            /* Calculate the length after aligning the base */
            RealSize = PcBiosMemoryMap[PcBiosMapCount].BaseAddress +
                       PcBiosMemoryMap[PcBiosMapCount].Length - RealBaseAddress;
            RealSize = (RealSize + MM_PAGE_SIZE - 1) & ~(MM_PAGE_SIZE - 1ULL);
        }

        /* Check if we can add this descriptor */
        if ((RealSize >= MM_PAGE_SIZE) && (MapCount < MaxMemoryMapSize))
        {
            /* Add the descriptor */
            MapCount = AddMemoryDescriptor(PcMemoryMap,
                                           MAX_BIOS_DESCRIPTORS,
                                           (PFN_NUMBER)(RealBaseAddress / MM_PAGE_SIZE),
                                           (PFN_NUMBER)(RealSize / MM_PAGE_SIZE),
                                           MemoryType);
        }

        PcBiosMapCount++;

        /* If the continuation value is zero or the
         * carry flag is set then this was
         * the last entry so we're done */
        if (Regs.x.ebx == 0x00000000)
        {
            TRACE("End Of System Memory Map!\n\n");
            break;
        }

    }

    return MapCount;
}
Esempio n. 3
0
static
VOID
MmCheckFreeldrImageFile(VOID)
{
    PIMAGE_NT_HEADERS NtHeaders;
    PIMAGE_FILE_HEADER FileHeader;
    PIMAGE_OPTIONAL_HEADER OptionalHeader;

    /* Get the NT headers */
    NtHeaders = RtlImageNtHeader(&__ImageBase);
    if (!NtHeaders)
    {
        ERR("Could not get NtHeaders!\n");
        FrLdrBugCheckWithMessage(
            FREELDR_IMAGE_CORRUPTION,
            __FILE__,
            __LINE__,
            "Could not get NtHeaders!\n");
    }

    /* Check the file header */
    FileHeader = &NtHeaders->FileHeader;
    if ((FileHeader->Machine != IMAGE_FILE_MACHINE_NATIVE) ||
        (FileHeader->NumberOfSections != FREELDR_SECTION_COUNT) ||
        (FileHeader->PointerToSymbolTable != 0) ||  // Symbols stripped
        (FileHeader->NumberOfSymbols != 0) ||       //    ""      ""
        (FileHeader->SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)))
    {
        ERR("FreeLdr FileHeader is invalid.\n");
        FrLdrBugCheckWithMessage(
            FREELDR_IMAGE_CORRUPTION,
            __FILE__,
            __LINE__,
            "FreeLdr FileHeader is invalid.\n"
            "Machine == 0x%lx, expected 0x%lx\n"
            "NumberOfSections == 0x%lx, expected 0x%lx\n"
            "PointerToSymbolTable == 0x%lx, expected 0\n"
            "NumberOfSymbols == 0x%lx, expected 0\n"
            "SizeOfOptionalHeader == 0x%lx, expected 0x%lx\n",
            FileHeader->Machine, IMAGE_FILE_MACHINE_NATIVE,
            FileHeader->NumberOfSections, FREELDR_SECTION_COUNT,
            FileHeader->PointerToSymbolTable,
            FileHeader->NumberOfSymbols,
            FileHeader->SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER));
    }

    /* Check the optional header */
    OptionalHeader = &NtHeaders->OptionalHeader;
    if ((OptionalHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) ||
        (OptionalHeader->Subsystem != IMAGE_SUBSYSTEM_NATIVE) ||
        (OptionalHeader->ImageBase != FREELDR_PE_BASE) ||
        (OptionalHeader->SizeOfImage > MAX_FREELDR_PE_SIZE) ||
        (OptionalHeader->SectionAlignment != OptionalHeader->FileAlignment))
    {
        ERR("FreeLdr OptionalHeader is invalid.\n");
        FrLdrBugCheckWithMessage(
            FREELDR_IMAGE_CORRUPTION,
            __FILE__,
            __LINE__,
            "FreeLdr OptionalHeader is invalid.\n"
            "Magic == 0x%lx, expected 0x%lx\n"
            "Subsystem == 0x%lx, expected 1 (native)\n"
            "ImageBase == 0x%lx, expected 0x%lx\n"
            "SizeOfImage == 0x%lx, maximum 0x%lx\n"
            "SectionAlignment 0x%lx doesn't match FileAlignment 0x%lx\n",
            OptionalHeader->Magic, IMAGE_NT_OPTIONAL_HDR_MAGIC,
            OptionalHeader->Subsystem,
            OptionalHeader->ImageBase, FREELDR_PE_BASE,
            OptionalHeader->SizeOfImage, MAX_FREELDR_PE_SIZE,
            OptionalHeader->SectionAlignment, OptionalHeader->FileAlignment);
    }

    /* Calculate the full image size */
    FrLdrImageSize = (ULONG_PTR)&__ImageBase + OptionalHeader->SizeOfImage - FREELDR_BASE;
}
Esempio n. 4
0
ULONG
AddMemoryDescriptor(
    IN OUT PFREELDR_MEMORY_DESCRIPTOR List,
    IN ULONG MaxCount,
    IN PFN_NUMBER BasePage,
    IN PFN_NUMBER PageCount,
    IN TYPE_OF_MEMORY MemoryType)
{
    ULONG Index, DescriptCount;
    PFN_NUMBER EndPage;
    TRACE("AddMemoryDescriptor(0x%Ix, 0x%Ix, %u)\n",
          BasePage, PageCount, MemoryType);

    EndPage = BasePage + PageCount;

    /* Skip over all descriptor below the new range */
    Index = 0;
    while ((List[Index].PageCount != 0) &&
           ((List[Index].BasePage + List[Index].PageCount) <= BasePage))
    {
        Index++;
    }

    /* Count the descriptors */
    DescriptCount = Index;
    while (List[DescriptCount].PageCount != 0)
    {
        DescriptCount++;
    }

    /* Check if the existing range conflicts with the new range */
    while ((List[Index].PageCount != 0) &&
           (List[Index].BasePage < EndPage))
    {
        TRACE("AddMemoryDescriptor conflict @%lu: new=[%lx:%lx], existing=[%lx,%lx]\n",
              Index, BasePage, PageCount, List[Index].BasePage, List[Index].PageCount);

        /*
         * We have 4 overlapping cases:
         *
         * Case              (a)       (b)       (c)       (d)
         * Existing range  |---|     |-----|    |---|      |---|
         * New range         |---|    |---|    |-----|   |---|
         *
         */

        /* Check if the existing range starts before the new range (a)/(b) */
        if (List[Index].BasePage < BasePage)
        {
            /* Check if the existing range extends beyond the new range (b) */
            if (List[Index].BasePage + List[Index].PageCount > EndPage)
            {
                /* Split the descriptor */
                RtlMoveMemory(&List[Index + 1],
                              &List[Index],
                              (DescriptCount - Index) * sizeof(List[0]));
                List[Index + 1].BasePage = EndPage;
                List[Index + 1].PageCount = List[Index].BasePage +
                                            List[Index].PageCount -
                                            List[Index + 1].BasePage;
                List[Index].PageCount = BasePage - List[Index].BasePage;
                Index++;
                DescriptCount++;
                break;
            }
            else
            {
                /* Crop the existing range and continue with the next range */
                List[Index].PageCount = BasePage - List[Index].BasePage;
                Index++;
            }
        }
        /* Check if the existing range is fully covered by the new range (c) */
        else if ((List[Index].BasePage + List[Index].PageCount) <=
                 EndPage)
        {
            /* Delete this descriptor */
            RtlMoveMemory(&List[Index],
                          &List[Index + 1],
                          (DescriptCount - Index) * sizeof(List[0]));
            DescriptCount--;
        }
        /* Otherwise the existing range ends after the new range (d) */
        else
        {
            /* Crop the existing range at the start and bail out */
            List[Index].PageCount -= EndPage - List[Index].BasePage;
            List[Index].BasePage = EndPage;
            break;
        }
    }

    /* Make sure we can still add a new descriptor */
    if (DescriptCount >= MaxCount)
    {
        FrLdrBugCheckWithMessage(
            MEMORY_INIT_FAILURE,
            __FILE__,
            __LINE__,
            "Ran out of static memory descriptors!");
    }

    /* Insert the new descriptor */
    if (Index < DescriptCount)
    {
        RtlMoveMemory(&List[Index + 1],
                      &List[Index],
                      (DescriptCount - Index) * sizeof(List[0]));
    }

    List[Index].BasePage = BasePage;
    List[Index].PageCount = PageCount;
    List[Index].MemoryType = MemoryType;
    DescriptCount++;

#if 0 // only enable on demand!
    DbgDumpMemoryMap(List);
#endif
    return DescriptCount;
}
Esempio n. 5
0
static
ULONG
PcMemGetBiosMemoryMap(PFREELDR_MEMORY_DESCRIPTOR MemoryMap, ULONG MaxMemoryMapSize)
{
    REGS Regs;
    ULONGLONG RealBaseAddress, EndAddress, RealSize;
    TYPE_OF_MEMORY MemoryType;
    ULONG Size, RequiredSize;
    ASSERT(PcBiosMapCount == 0);

    TRACE("GetBiosMemoryMap()\n");

    /* Make sure the usable memory is large enough. To do this we check the 16
       bit value at address 0x413 inside the BDA, which gives us the usable size
       in KB */
    Size = (*(PUSHORT)(ULONG_PTR)0x413) * 1024;
    RequiredSize = FREELDR_BASE + FrLdrImageSize + PAGE_SIZE;
    if (Size < RequiredSize)
    {
        FrLdrBugCheckWithMessage(
            MEMORY_INIT_FAILURE,
            __FILE__,
            __LINE__,
            "The BIOS reported a usable memory range up to 0x%x, which is too small!\n"
            "Required size is 0x%x\n\n"
            "If you see this, please report to the ReactOS team!",
            Size, RequiredSize);
    }

    /* Int 15h AX=E820h
     * Newer BIOSes - GET SYSTEM MEMORY MAP
     *
     * AX = E820h
     * EAX = 0000E820h
     * EDX = 534D4150h ('SMAP')
     * EBX = continuation value or 00000000h to start at beginning of map
     * ECX = size of buffer for result, in bytes (should be >= 20 bytes)
     * ES:DI -> buffer for result
     * Return:
     * CF clear if successful
     * EAX = 534D4150h ('SMAP')
     * ES:DI buffer filled
     * EBX = next offset from which to copy or 00000000h if all done
     * ECX = actual length returned in bytes
     * CF set on error
     * AH = error code (86h)
     */
    Regs.x.ebx = 0x00000000;

    while (PcBiosMapCount < MAX_BIOS_DESCRIPTORS)
    {
        /* Setup the registers for the BIOS call */
        Regs.x.eax = 0x0000E820;
        Regs.x.edx = 0x534D4150; /* ('SMAP') */
        /* Regs.x.ebx = 0x00000001;  Continuation value already set */
        Regs.x.ecx = sizeof(BIOS_MEMORY_MAP);
        Regs.w.es = BIOSCALLBUFSEGMENT;
        Regs.w.di = BIOSCALLBUFOFFSET;
        Int386(0x15, &Regs, &Regs);

        TRACE("Memory Map Entry %d\n", PcBiosMapCount);
        TRACE("Int15h AX=E820h\n");
        TRACE("EAX = 0x%x\n", Regs.x.eax);
        TRACE("EBX = 0x%x\n", Regs.x.ebx);
        TRACE("ECX = 0x%x\n", Regs.x.ecx);
        TRACE("CF set = %s\n", (Regs.x.eflags & EFLAGS_CF) ? "TRUE" : "FALSE");

        /* If the BIOS didn't return 'SMAP' in EAX then
         * it doesn't support this call. If CF is set, we're done */
        if (Regs.x.eax != 0x534D4150 || !INT386_SUCCESS(Regs))
        {
            break;
        }

        /* Copy data to global buffer */
        RtlCopyMemory(&PcBiosMemoryMap[PcBiosMapCount], (PVOID)BIOSCALLBUFFER, Regs.x.ecx);

        TRACE("BaseAddress: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].BaseAddress);
        TRACE("Length: 0x%llx\n", PcBiosMemoryMap[PcBiosMapCount].Length);
        TRACE("Type: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Type);
        TRACE("Reserved: 0x%lx\n", PcBiosMemoryMap[PcBiosMapCount].Reserved);
        TRACE("\n");

        /* Check if this is free memory */
        if (PcBiosMemoryMap[PcBiosMapCount].Type == BiosMemoryUsable)
        {
            MemoryType = LoaderFree;

            /* Align up base of memory range */
            RealBaseAddress = ALIGN_UP_BY(PcBiosMemoryMap[PcBiosMapCount].BaseAddress,
                                          PAGE_SIZE);

            /* Calculate aligned EndAddress */
            EndAddress = PcBiosMemoryMap[PcBiosMapCount].BaseAddress +
                         PcBiosMemoryMap[PcBiosMapCount].Length;
            EndAddress = ALIGN_DOWN_BY(EndAddress, PAGE_SIZE);

            /* Check if there is anything left */
            if (EndAddress <= RealBaseAddress)
            {
                /* This doesn't span any page, so continue with next range */
                continue;
            }

            /* Calculate the length of the aligned range */
            RealSize = EndAddress - RealBaseAddress;
        }
        else
        {
            if (PcBiosMemoryMap[PcBiosMapCount].Type == BiosMemoryReserved)
                MemoryType = LoaderFirmwarePermanent;
            else
                MemoryType = LoaderSpecialMemory;

            /* Align down base of memory area */
            RealBaseAddress = ALIGN_DOWN_BY(PcBiosMemoryMap[PcBiosMapCount].BaseAddress,
                                            PAGE_SIZE);

            /* Calculate the length after aligning the base */
            RealSize = PcBiosMemoryMap[PcBiosMapCount].BaseAddress +
                       PcBiosMemoryMap[PcBiosMapCount].Length - RealBaseAddress;
            RealSize = ALIGN_UP_BY(RealSize, PAGE_SIZE);
        }

        /* Check if we can add this descriptor */
        if ((RealSize >= MM_PAGE_SIZE) && (PcMapCount < MaxMemoryMapSize))
        {
            /* Add the descriptor */
            PcMapCount = AddMemoryDescriptor(PcMemoryMap,
                                           MAX_BIOS_DESCRIPTORS,
                                           (PFN_NUMBER)(RealBaseAddress / MM_PAGE_SIZE),
                                           (PFN_NUMBER)(RealSize / MM_PAGE_SIZE),
                                           MemoryType);
        }

        PcBiosMapCount++;

        /* If the continuation value is zero or the
         * carry flag is set then this was
         * the last entry so we're done */
        if (Regs.x.ebx == 0x00000000)
        {
            TRACE("End Of System Memory Map!\n\n");
            break;
        }
    }

    TRACE("GetBiosMemoryMap end, PcBiosMapCount = %ld\n", PcBiosMapCount);
    return PcBiosMapCount;
}