mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 17:45:41 +00:00
[FREELDR] Obtain Xbox memory map via multiboot spec (#1971)
- Also obtain framebuffer memory size the same way. References: https://wiki.osdev.org/Detecting_Memory_(x86)#Memory_Map_Via_GRUB https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format CORE-16216 CORE-16300
This commit is contained in:
parent
7523a7b138
commit
96692636e4
4 changed files with 206 additions and 18 deletions
|
@ -29,9 +29,13 @@
|
||||||
* the header signature and uses the header to load it.
|
* the header signature and uses the header to load it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define MB_INFO_SIZE 60 /* sizeof(multiboot_info_t) */
|
||||||
#define MB_INFO_FLAGS_OFFSET 0
|
#define MB_INFO_FLAGS_OFFSET 0
|
||||||
#define MB_INFO_BOOT_DEVICE_OFFSET 12
|
#define MB_INFO_BOOT_DEVICE_OFFSET 12
|
||||||
#define MB_INFO_COMMAND_LINE_OFFSET 16
|
#define MB_INFO_COMMAND_LINE_OFFSET 16
|
||||||
|
#define MB_INFO_MMAP_LEN_OFFSET 44
|
||||||
|
#define MB_INFO_MMAP_ADDR_OFFSET 48
|
||||||
|
#define MB_MMAP_SIZE 480 /* 20 * sizeof(memory_map_t) - up to 20 entries */
|
||||||
#define CMDLINE_SIZE 256
|
#define CMDLINE_SIZE 256
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -91,6 +95,35 @@ MultibootEntry:
|
||||||
cmp eax, MULTIBOOT_BOOTLOADER_MAGIC
|
cmp eax, MULTIBOOT_BOOTLOADER_MAGIC
|
||||||
jne mbfail
|
jne mbfail
|
||||||
|
|
||||||
|
/* Save multiboot info structure */
|
||||||
|
mov esi, ebx
|
||||||
|
mov edi, offset MultibootInfo + INITIAL_BASE - FREELDR_BASE
|
||||||
|
mov ecx, (MB_INFO_SIZE / 4)
|
||||||
|
rep movsd
|
||||||
|
mov dword ptr ds:[MultibootInfo + INITIAL_BASE - FREELDR_BASE + MB_INFO_MMAP_ADDR_OFFSET], 0
|
||||||
|
mov dword ptr ds:[_MultibootInfoPtr + INITIAL_BASE - FREELDR_BASE], offset MultibootInfo
|
||||||
|
|
||||||
|
/* See if the memory map was passed in */
|
||||||
|
test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_MEMORY_MAP
|
||||||
|
jz mbchk_command_line
|
||||||
|
/* Check memory map length */
|
||||||
|
mov ecx, dword ptr ds:[ebx + MB_INFO_MMAP_LEN_OFFSET]
|
||||||
|
test ecx, ecx
|
||||||
|
jz mbchk_command_line
|
||||||
|
cmp ecx, MB_MMAP_SIZE
|
||||||
|
jg mbchk_command_line
|
||||||
|
/* Check memory map address */
|
||||||
|
mov esi, dword ptr ds:[ebx + MB_INFO_MMAP_ADDR_OFFSET]
|
||||||
|
test esi, esi
|
||||||
|
jz mbchk_command_line
|
||||||
|
/* Save memory map structure */
|
||||||
|
mov edi, offset MultibootMemoryMap + INITIAL_BASE - FREELDR_BASE
|
||||||
|
shr ecx, 2
|
||||||
|
rep movsd
|
||||||
|
/* Relocate memory map address */
|
||||||
|
mov dword ptr ds:[MultibootInfo + INITIAL_BASE - FREELDR_BASE + MB_INFO_MMAP_ADDR_OFFSET], offset MultibootMemoryMap
|
||||||
|
|
||||||
|
mbchk_command_line:
|
||||||
/* Save command line */
|
/* Save command line */
|
||||||
test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
|
test dword ptr ds:[ebx + MB_INFO_FLAGS_OFFSET], MB_INFO_FLAG_COMMAND_LINE
|
||||||
jz mb2
|
jz mb2
|
||||||
|
@ -171,6 +204,16 @@ gdtptr:
|
||||||
.word HEX(17) /* Limit */
|
.word HEX(17) /* Limit */
|
||||||
.long gdt /* Base Address */
|
.long gdt /* Base Address */
|
||||||
|
|
||||||
|
PUBLIC _MultibootInfoPtr
|
||||||
|
_MultibootInfoPtr:
|
||||||
|
.long 0
|
||||||
|
|
||||||
|
MultibootInfo:
|
||||||
|
.space MB_INFO_SIZE
|
||||||
|
|
||||||
|
MultibootMemoryMap:
|
||||||
|
.space MB_MMAP_SIZE
|
||||||
|
|
||||||
PUBLIC cmdline
|
PUBLIC cmdline
|
||||||
cmdline:
|
cmdline:
|
||||||
.space CMDLINE_SIZE
|
.space CMDLINE_SIZE
|
||||||
|
|
|
@ -26,6 +26,7 @@ DBG_DEFAULT_CHANNEL(MEMORY);
|
||||||
|
|
||||||
static ULONG InstalledMemoryMb = 0;
|
static ULONG InstalledMemoryMb = 0;
|
||||||
static ULONG AvailableMemoryMb = 0;
|
static ULONG AvailableMemoryMb = 0;
|
||||||
|
extern multiboot_info_t * MultibootInfoPtr;
|
||||||
extern PVOID FrameBuffer;
|
extern PVOID FrameBuffer;
|
||||||
extern ULONG FrameBufferSize;
|
extern ULONG FrameBufferSize;
|
||||||
|
|
||||||
|
@ -98,30 +99,107 @@ XboxMemInit(VOID)
|
||||||
AvailableMemoryMb = InstalledMemoryMb;
|
AvailableMemoryMb = InstalledMemoryMb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memory_map_t *
|
||||||
|
XboxGetMultibootMemoryMap(INT * Count)
|
||||||
|
{
|
||||||
|
memory_map_t * MemoryMap;
|
||||||
|
|
||||||
|
if (!MultibootInfoPtr)
|
||||||
|
{
|
||||||
|
ERR("Multiboot info structure not found!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(MultibootInfoPtr->flags & MB_INFO_FLAG_MEMORY_MAP))
|
||||||
|
{
|
||||||
|
ERR("Multiboot memory map is not passed!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryMap = (memory_map_t *)MultibootInfoPtr->mmap_addr;
|
||||||
|
|
||||||
|
if (!MemoryMap ||
|
||||||
|
MultibootInfoPtr->mmap_length == 0 ||
|
||||||
|
MultibootInfoPtr->mmap_length % sizeof(memory_map_t) != 0)
|
||||||
|
{
|
||||||
|
ERR("Multiboot memory map structure is malformed!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*Count = MultibootInfoPtr->mmap_length / sizeof(memory_map_t);
|
||||||
|
return MemoryMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPE_OF_MEMORY
|
||||||
|
XboxMultibootMemoryType(ULONG Type)
|
||||||
|
{
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case 0: // Video RAM
|
||||||
|
return LoaderFirmwarePermanent;
|
||||||
|
case 1: // Available RAM
|
||||||
|
return LoaderFree;
|
||||||
|
case 3: // ACPI area
|
||||||
|
return LoaderFirmwareTemporary;
|
||||||
|
case 4: // Hibernation area
|
||||||
|
return LoaderSpecialMemory;
|
||||||
|
case 5: // Reserved or invalid memory
|
||||||
|
return LoaderSpecialMemory;
|
||||||
|
default:
|
||||||
|
return LoaderFirmwarePermanent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FREELDR_MEMORY_DESCRIPTOR XboxMemoryMap[MAX_BIOS_DESCRIPTORS + 1];
|
FREELDR_MEMORY_DESCRIPTOR XboxMemoryMap[MAX_BIOS_DESCRIPTORS + 1];
|
||||||
|
|
||||||
PFREELDR_MEMORY_DESCRIPTOR
|
PFREELDR_MEMORY_DESCRIPTOR
|
||||||
XboxMemGetMemoryMap(ULONG *MemoryMapSize)
|
XboxMemGetMemoryMap(ULONG *MemoryMapSize)
|
||||||
{
|
{
|
||||||
|
memory_map_t * MbMap;
|
||||||
|
INT Count, i;
|
||||||
|
|
||||||
TRACE("XboxMemGetMemoryMap()\n");
|
TRACE("XboxMemGetMemoryMap()\n");
|
||||||
/* FIXME: Obtain memory map via multiboot spec */
|
|
||||||
|
|
||||||
/* Synthesize memory map */
|
MbMap = XboxGetMultibootMemoryMap(&Count);
|
||||||
|
if (MbMap)
|
||||||
/* Available RAM block */
|
|
||||||
SetMemory(XboxMemoryMap,
|
|
||||||
0,
|
|
||||||
AvailableMemoryMb * 1024 * 1024,
|
|
||||||
LoaderFree);
|
|
||||||
|
|
||||||
if (FrameBufferSize != 0)
|
|
||||||
{
|
{
|
||||||
/* Video memory */
|
/* Obtain memory map via multiboot spec */
|
||||||
ReserveMemory(XboxMemoryMap,
|
|
||||||
(ULONG_PTR)FrameBuffer,
|
for (i = 0; i < Count; i++, MbMap++)
|
||||||
FrameBufferSize,
|
{
|
||||||
LoaderFirmwarePermanent,
|
TRACE("i = %d, base_addr_low = 0x%p, length_low = 0x%p\n", i, MbMap->base_addr_low, MbMap->length_low);
|
||||||
"Video memory");
|
|
||||||
|
if (MbMap->base_addr_high > 0 || MbMap->length_high > 0)
|
||||||
|
{
|
||||||
|
ERR("Memory descriptor base or size is greater than 4 GB, should not happen on Xbox!\n");
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMemory(XboxMemoryMap,
|
||||||
|
MbMap->base_addr_low,
|
||||||
|
MbMap->length_low,
|
||||||
|
XboxMultibootMemoryType(MbMap->type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Synthesize memory map */
|
||||||
|
|
||||||
|
/* Available RAM block */
|
||||||
|
SetMemory(XboxMemoryMap,
|
||||||
|
0,
|
||||||
|
AvailableMemoryMb * 1024 * 1024,
|
||||||
|
LoaderFree);
|
||||||
|
|
||||||
|
if (FrameBufferSize != 0)
|
||||||
|
{
|
||||||
|
/* Video memory */
|
||||||
|
ReserveMemory(XboxMemoryMap,
|
||||||
|
(ULONG_PTR)FrameBuffer,
|
||||||
|
FrameBufferSize,
|
||||||
|
LoaderFirmwarePermanent,
|
||||||
|
"Video memory");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*MemoryMapSize = PcMemFinalizeMemoryMap(XboxMemoryMap);
|
*MemoryMapSize = PcMemFinalizeMemoryMap(XboxMemoryMap);
|
||||||
|
|
|
@ -30,6 +30,7 @@ static ULONG ScreenWidth;
|
||||||
static ULONG ScreenHeight;
|
static ULONG ScreenHeight;
|
||||||
static ULONG BytesPerPixel;
|
static ULONG BytesPerPixel;
|
||||||
static ULONG Delta;
|
static ULONG Delta;
|
||||||
|
extern multiboot_info_t * MultibootInfoPtr;
|
||||||
|
|
||||||
#define CHAR_WIDTH 8
|
#define CHAR_WIDTH 8
|
||||||
#define CHAR_HEIGHT 16
|
#define CHAR_HEIGHT 16
|
||||||
|
@ -127,6 +128,46 @@ NvGetCrtc(UCHAR Index)
|
||||||
return *((PUCHAR) NV2A_CRTC_REGISTER_VALUE);
|
return *((PUCHAR) NV2A_CRTC_REGISTER_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
XboxGetFramebufferSize(PVOID Offset)
|
||||||
|
{
|
||||||
|
memory_map_t * MemoryMap;
|
||||||
|
INT Count, i;
|
||||||
|
|
||||||
|
if (!MultibootInfoPtr)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(MultibootInfoPtr->flags & MB_INFO_FLAG_MEMORY_MAP))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryMap = (memory_map_t *)MultibootInfoPtr->mmap_addr;
|
||||||
|
|
||||||
|
if (!MemoryMap ||
|
||||||
|
MultibootInfoPtr->mmap_length == 0 ||
|
||||||
|
MultibootInfoPtr->mmap_length % sizeof(memory_map_t) != 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Count = MultibootInfoPtr->mmap_length / sizeof(memory_map_t);
|
||||||
|
for (i = 0; i < Count; i++, MemoryMap++)
|
||||||
|
{
|
||||||
|
TRACE("i = %d, base_addr_low = 0x%p, MemoryMap->length_low = 0x%p\n", i, MemoryMap->base_addr_low, MemoryMap->length_low);
|
||||||
|
|
||||||
|
if (MemoryMap->base_addr_low == (ULONG)Offset && MemoryMap->base_addr_high == 0)
|
||||||
|
{
|
||||||
|
TRACE("Video memory found\n");
|
||||||
|
return MemoryMap->length_low;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ERR("Video memory not found!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
XboxVideoInit(VOID)
|
XboxVideoInit(VOID)
|
||||||
{
|
{
|
||||||
|
@ -135,8 +176,13 @@ XboxVideoInit(VOID)
|
||||||
/* Verify that framebuffer address is page-aligned */
|
/* Verify that framebuffer address is page-aligned */
|
||||||
ASSERT((ULONG_PTR)FrameBuffer % PAGE_SIZE == 0);
|
ASSERT((ULONG_PTR)FrameBuffer % PAGE_SIZE == 0);
|
||||||
|
|
||||||
/* FIXME: obtain fb size from firmware somehow (Cromwell reserves high 4 MB of RAM) */
|
/* Obtain framebuffer memory size from multiboot memory map */
|
||||||
FrameBufferSize = 4 * 1024 * 1024;
|
if ((FrameBufferSize = XboxGetFramebufferSize(FrameBuffer)) == 0)
|
||||||
|
{
|
||||||
|
/* Fallback to Cromwell standard which reserves high 4 MB of RAM */
|
||||||
|
FrameBufferSize = 4 * 1024 * 1024;
|
||||||
|
WARN("Could not detect framebuffer memory size, fallback to 4 MB\n");
|
||||||
|
}
|
||||||
|
|
||||||
ScreenWidth = *((PULONG) NV2A_RAMDAC_FP_HVALID_END) + 1;
|
ScreenWidth = *((PULONG) NV2A_RAMDAC_FP_HVALID_END) + 1;
|
||||||
ScreenHeight = *((PULONG) NV2A_RAMDAC_FP_VVALID_END) + 1;
|
ScreenHeight = *((PULONG) NV2A_RAMDAC_FP_VVALID_END) + 1;
|
||||||
|
|
|
@ -90,6 +90,27 @@ typedef struct elf_section_header_table
|
||||||
unsigned long shndx;
|
unsigned long shndx;
|
||||||
} elf_section_header_table_t;
|
} elf_section_header_table_t;
|
||||||
|
|
||||||
|
/* The Multiboot information. */
|
||||||
|
typedef struct multiboot_info
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned long mem_lower;
|
||||||
|
unsigned long mem_upper;
|
||||||
|
unsigned long boot_device;
|
||||||
|
unsigned long cmdline;
|
||||||
|
unsigned long mods_count;
|
||||||
|
unsigned long mods_addr;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
aout_symbol_table_t aout_sym;
|
||||||
|
elf_section_header_table_t elf_sec;
|
||||||
|
} u;
|
||||||
|
unsigned long mmap_length;
|
||||||
|
unsigned long mmap_addr;
|
||||||
|
unsigned long drives_length;
|
||||||
|
unsigned long drives_addr;
|
||||||
|
} multiboot_info_t;
|
||||||
|
|
||||||
/* The memory map. Be careful that the offset 0 is base_addr_low
|
/* The memory map. Be careful that the offset 0 is base_addr_low
|
||||||
but no size. */
|
but no size. */
|
||||||
typedef struct memory_map
|
typedef struct memory_map
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue