reactos/boot/freeldr/freeldr/arch/i386/machxbox.c
Hermès Bélusca-Maïto 4843c1a954
[FREELDR] Other enhancements.
- Add optional arguments BootDrive and BootPartition to
  ChainLoadBiosBootSectorCode() so as not to modify explicitly the
  FrldrBootDrive and FrldrBootPartition variables, that should remain
  purely internal.

- Implement ChainLoadBiosBootSectorCode() for x64.

- Get rid of the machine-specific DiskGetBootPath(), and instead do its
  job only once in the machine-specific InitializeBootDevices() (or in
  MachInit() for PPC).
  Cache the result of this operation into the globally-accessible
  FrldrBootPath buffer. This avoids the unneeded calls to (Mach)DiskGetBootPath()
  we used to do before.
  Also remove the separate distinction between the PC and XBOX versions
  of this functionality.

- Move the PC-specific DiskIsDriveRemovable() and DiskGetBootPath()
  as well as the disk-IO-error functionality, back into the
  corresponding PC-arch files.

- Simplify IniFileInitialize(), getting rid of IniOpenIniFile().
2019-09-13 15:18:07 +02:00

308 lines
9.5 KiB
C

/*
* FreeLoader
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <freeldr.h>
#include <debug.h>
DBG_DEFAULT_CHANNEL(HWDETECT);
BOOLEAN
XboxFindPciBios(PPCI_REGISTRY_INFO BusData)
{
/* We emulate PCI BIOS here, there are 2 known working PCI buses on an original Xbox */
BusData->NoBuses = 2;
BusData->MajorRevision = 1;
BusData->MinorRevision = 0;
BusData->HardwareMechanism = 1;
return TRUE;
}
extern
VOID
DetectSerialPointerPeripheral(PCONFIGURATION_COMPONENT_DATA ControllerKey, PUCHAR Base);
static
ULONG
XboxGetSerialPort(ULONG Index, PULONG Irq)
{
/*
* Xbox may have maximum two Serial COM ports
* if the Super I/O chip is connected via LPC
*/
static const UCHAR Device[MAX_XBOX_COM_PORTS] = {LPC_DEVICE_SERIAL_PORT_1, LPC_DEVICE_SERIAL_PORT_2};
ULONG ComBase = 0;
// Enter Configuration
WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_ENTER_CONFIG_KEY);
// Select serial device
WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_NUMBER);
WRITE_PORT_UCHAR(LPC_IO_BASE + 1, Device[Index]);
// Check if selected device is active
WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_ACTIVATE);
if (READ_PORT_UCHAR(LPC_IO_BASE + 1) == 1)
{
// Read LSB
WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_BASE_ADDRESS_LOW);
ComBase = READ_PORT_UCHAR(LPC_IO_BASE + 1);
// Read MSB
WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_BASE_ADDRESS_HIGH);
ComBase |= (READ_PORT_UCHAR(LPC_IO_BASE + 1) << 8);
// Read IRQ
WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_CONFIG_DEVICE_INTERRUPT);
*Irq = READ_PORT_UCHAR(LPC_IO_BASE + 1);
}
// Exit Configuration
WRITE_PORT_UCHAR(LPC_IO_BASE, LPC_EXIT_CONFIG_KEY);
return ComBase;
}
extern
VOID
DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey, GET_SERIAL_PORT MachGetSerialPort, ULONG Count);
VOID
XboxGetExtendedBIOSData(PULONG ExtendedBIOSDataArea, PULONG ExtendedBIOSDataSize)
{
TRACE("XboxGetExtendedBIOSData(): UNIMPLEMENTED\n");
*ExtendedBIOSDataArea = 0;
*ExtendedBIOSDataSize = 0;
}
// NOTE: Similar to machpc.c!PcGetHarddiskConfigurationData(),
// but without extended geometry support.
static
PCM_PARTIAL_RESOURCE_LIST
XboxGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
{
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
//EXTENDED_GEOMETRY ExtGeometry;
GEOMETRY Geometry;
ULONG Size;
//
// Initialize returned size
//
*pSize = 0;
/* Set 'Configuration Data' value */
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
if (PartialResourceList == NULL)
{
ERR("Failed to allocate a full resource descriptor\n");
return NULL;
}
memset(PartialResourceList, 0, Size);
PartialResourceList->Version = 1;
PartialResourceList->Revision = 1;
PartialResourceList->Count = 1;
PartialResourceList->PartialDescriptors[0].Type =
CmResourceTypeDeviceSpecific;
// PartialResourceList->PartialDescriptors[0].ShareDisposition =
// PartialResourceList->PartialDescriptors[0].Flags =
PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
/* Get pointer to geometry data */
DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
/* Get the disk geometry */
//ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
if (MachDiskGetDriveGeometry(DriveNumber, &Geometry))
{
DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
DiskGeometry->SectorsPerTrack = Geometry.Sectors;
DiskGeometry->NumberOfHeads = Geometry.Heads;
}
else
{
ERR("Reading disk geometry failed\n");
FrLdrHeapFree(PartialResourceList, TAG_HW_RESOURCE_LIST);
return NULL;
}
TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
DriveNumber,
DiskGeometry->NumberOfCylinders,
DiskGeometry->NumberOfHeads,
DiskGeometry->SectorsPerTrack,
DiskGeometry->BytesPerSector);
//
// Return configuration data
//
*pSize = Size;
return PartialResourceList;
}
static
VOID
DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
{
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
PCONFIGURATION_COMPONENT_DATA BusKey;
ULONG Size;
/* Set 'Configuration Data' value */
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
if (PartialResourceList == NULL)
{
TRACE("Failed to allocate resource descriptor\n");
return;
}
/* Initialize resource descriptor */
memset(PartialResourceList, 0, Size);
PartialResourceList->Version = 1;
PartialResourceList->Revision = 1;
PartialResourceList->Count = 0;
/* Create new bus key */
FldrCreateComponentKey(SystemKey,
AdapterClass,
MultiFunctionAdapter,
0x0,
0x0,
0xFFFFFFFF,
"ISA",
PartialResourceList,
Size,
&BusKey);
/* Increment bus number */
(*BusNumber)++;
/* Detect ISA/BIOS devices */
DetectBiosDisks(SystemKey, BusKey);
DetectSerialPorts(BusKey, XboxGetSerialPort, MAX_XBOX_COM_PORTS);
/* FIXME: Detect more ISA devices */
}
static
UCHAR
XboxGetFloppyCount(VOID)
{
/* On a PC we use CMOS/RTC I/O ports 0x70 and 0x71 to detect floppies.
* However an Xbox CMOS memory range [0x10, 0x70) and [0x80, 0x100)
* is filled with 0x55 0xAA 0x55 0xAA ... byte pattern which is used
* to validate the date/time settings by Xbox OS.
*
* Technically it's possible to connect a floppy drive to Xbox, but
* CMOS detection method should not be used here. */
WARN("XboxGetFloppyCount() is UNIMPLEMENTED, returning 0\n");
return 0;
}
PCONFIGURATION_COMPONENT_DATA
XboxHwDetect(VOID)
{
PCONFIGURATION_COMPONENT_DATA SystemKey;
ULONG BusNumber = 0;
TRACE("DetectHardware()\n");
/* Create the 'System' key */
FldrCreateSystemKey(&SystemKey);
GetHarddiskConfigurationData = XboxGetHarddiskConfigurationData;
FindPciBios = XboxFindPciBios;
/* TODO: Build actual xbox's hardware configuration tree */
DetectPciBios(SystemKey, &BusNumber);
DetectIsaBios(SystemKey, &BusNumber);
TRACE("DetectHardware() Done\n");
return SystemKey;
}
VOID XboxHwIdle(VOID)
{
/* UNIMPLEMENTED */
}
/******************************************************************************/
VOID
XboxMachInit(const char *CmdLine)
{
/* Set LEDs to red before anything is initialized */
XboxSetLED("rrrr");
/* Initialize our stuff */
XboxMemInit();
XboxVideoInit();
/* Setup vtbl */
MachVtbl.ConsPutChar = XboxConsPutChar;
MachVtbl.ConsKbHit = XboxConsKbHit;
MachVtbl.ConsGetCh = XboxConsGetCh;
MachVtbl.VideoClearScreen = XboxVideoClearScreen;
MachVtbl.VideoSetDisplayMode = XboxVideoSetDisplayMode;
MachVtbl.VideoGetDisplaySize = XboxVideoGetDisplaySize;
MachVtbl.VideoGetBufferSize = XboxVideoGetBufferSize;
MachVtbl.VideoGetFontsFromFirmware = XboxVideoGetFontsFromFirmware;
MachVtbl.VideoSetTextCursorPosition = XboxVideoSetTextCursorPosition;
MachVtbl.VideoHideShowTextCursor = XboxVideoHideShowTextCursor;
MachVtbl.VideoPutChar = XboxVideoPutChar;
MachVtbl.VideoCopyOffScreenBufferToVRAM = XboxVideoCopyOffScreenBufferToVRAM;
MachVtbl.VideoIsPaletteFixed = XboxVideoIsPaletteFixed;
MachVtbl.VideoSetPaletteColor = XboxVideoSetPaletteColor;
MachVtbl.VideoGetPaletteColor = XboxVideoGetPaletteColor;
MachVtbl.VideoSync = XboxVideoSync;
MachVtbl.Beep = PcBeep;
MachVtbl.PrepareForReactOS = XboxPrepareForReactOS;
MachVtbl.GetMemoryMap = XboxMemGetMemoryMap;
MachVtbl.GetExtendedBIOSData = XboxGetExtendedBIOSData;
MachVtbl.GetFloppyCount = XboxGetFloppyCount;
MachVtbl.DiskReadLogicalSectors = XboxDiskReadLogicalSectors;
MachVtbl.DiskGetDriveGeometry = XboxDiskGetDriveGeometry;
MachVtbl.DiskGetCacheableBlockCount = XboxDiskGetCacheableBlockCount;
MachVtbl.GetTime = XboxGetTime;
MachVtbl.InitializeBootDevices = PcInitializeBootDevices;
MachVtbl.HwDetect = XboxHwDetect;
MachVtbl.HwIdle = XboxHwIdle;
/* Set LEDs to orange after init */
XboxSetLED("oooo");
}
VOID
XboxPrepareForReactOS(VOID)
{
/* On XBOX, prepare video and turn off the floppy motor */
XboxVideoPrepareForReactOS();
DiskStopFloppyMotor();
}
/* EOF */