diff --git a/reactos/boot/freeldr/FREELDR.INI b/reactos/boot/freeldr/FREELDR.INI index e65ec6eadbd..7177121b824 100644 --- a/reactos/boot/freeldr/FREELDR.INI +++ b/reactos/boot/freeldr/FREELDR.INI @@ -29,6 +29,7 @@ ; [FREELOADER] Section Commands: ; +; Debug - FreeLoader debugging port parameters, e.g. /DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 ; MessageBox - displays the specified text in a message box upon bootup ; MessageLine - adds a new line of text to a message box (must come before MessageBox command) ; TitleText - text that is displayed in the title box @@ -50,15 +51,15 @@ ; [OS-General] Section Commands: ; -; BootType - sets the boot type: ReactOS, Linux, BootSector, Partition, Drive -; BootPath - ARC path e.g. multi(0)disk(0)rdisk(x)partition(y) +; BootType - sets the boot type: Windows, WindowsNT40, Windows2003, Linux, BootSector, Partition, Drive, ReactOSSetup +; BootPath - ARC path, e.g. multi(0)disk(0)rdisk(x)partition(y) ; DriveMap - maps a BIOS drive number to another (i.e. DriveMap=hd1,hd0 maps harddisk1 to harddisk0 or DriveMap=fd1,fd0) ; [BootSector OSType] Section Commands: ; ; BootSector - sets the filename of the bootsector to be loaded -; [ReactOS OSType] Section Commands: +; [Windows(NT40|2003) OSType] Section Commands: ; ; SystemPath - sets the system root path (must be a valid ARC - Path): ; multi(0)disk(0)rdisk(0)partition(1)\reactos @@ -110,7 +111,7 @@ DriveD="Drive D:" ; Load ReactOS from harddisk (drive C:) [ReactOSHD] -BootType=ReactOS +BootType=Windows2003 SystemPath=multi(0)disk(0)rdisk(0)partition(1)\reactos Options=/DEBUGPORT=SCREEN Kernel=\REACTOS\SYSTEM32\NTOSKRNL.EXE @@ -118,14 +119,14 @@ Hal=\REACTOS\SYSTEM32\HAL.DLL ; Load ReactOS from floppy (drive A:) [ReactOSFloppy] -BootType=ReactOS +BootType=Windows2003 SystemPath=multi(0)disk(0)fdisk(0) Options=/DEBUGPORT=SCREEN Kernel=\reactos\NTOSKRNL.EXE Hal=\reactos\HAL.DLL ;[ReactOS (Debug)] -;BootType=ReactOS +;BootType=Windows2003 ;SystemPath=multi(0)disk(0)rdisk(0)partition(1)\reactos ;Options=/DEBUG /DEBUGPORT=COM1 /BAUDRATE=19200 ;Kernel=\NTOSKRNL.EXE diff --git a/reactos/boot/freeldr/freeldr/bootmgr.c b/reactos/boot/freeldr/freeldr/bootmgr.c index 37ccb2aae60..fbe49838ab8 100644 --- a/reactos/boot/freeldr/freeldr/bootmgr.c +++ b/reactos/boot/freeldr/freeldr/bootmgr.c @@ -20,6 +20,7 @@ /* INCLUDES *******************************************************************/ #include +#include /* GLOBALS ********************************************************************/ @@ -131,7 +132,7 @@ ULONG GetDefaultOperatingSystem(OperatingSystemItem* OperatingSystemList, ULONG if (DefaultOSName != NULL) { - for (Idx = 0; Idx #include -/* MACROS *******************************************************************/ - #if DBG +/* STATIC VARIABLES ***********************************************************/ + #define DEFAULT_BAUD_RATE 19200 +#if defined(_M_IX86) || defined(_M_AMD64) +static const ULONG BaseArray[] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8}; +#elif defined(_M_PPC) +static const ULONG BaseArray[] = {0, 0x800003F8}; +#elif defined(_M_MIPS) +static const ULONG BaseArray[] = {0, 0x80006000, 0x80007000}; +#elif defined(_M_ARM) +static const ULONG BaseArray[] = {0, 0xF1012000}; +#else +#error Unknown architecture +#endif -/* STATIC VARIABLES *********************************************************/ - -static ULONG BaseArray[] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8}; +#define MAX_COM_PORTS (sizeof(BaseArray) / sizeof(BaseArray[0]) - 1) /* The COM port must only be initialized once! */ -static CPPORT Rs232ComPort; -static BOOLEAN PortInitialized = FALSE; +static ULONG Rs232ComPort = 0; +static CPPORT Rs232ComPortInfo; - -/* FUNCTIONS *********************************************************/ +/* FUNCTIONS ******************************************************************/ BOOLEAN Rs232PortInitialize(IN ULONG ComPort, IN ULONG BaudRate) @@ -48,77 +58,73 @@ BOOLEAN Rs232PortInitialize(IN ULONG ComPort, NTSTATUS Status; PUCHAR Address; - if (PortInitialized == FALSE) - { - if (BaudRate == 0) - { - BaudRate = DEFAULT_BAUD_RATE; - } + /* + * Check whether it's the first time we initialize a COM port. + * If not, check whether the specified one was already initialized. + */ + if ((Rs232ComPort != 0) && (Rs232ComPort == ComPort)) + return TRUE; - if (ComPort == 0) - { - if (CpDoesPortExist(UlongToPtr(BaseArray[2]))) - { - Address = UlongToPtr(BaseArray[2]); - } - else if (CpDoesPortExist(UlongToPtr(BaseArray[1]))) - { - Address = UlongToPtr(BaseArray[1]); - } - else - { - return FALSE; - } - } - else if (ComPort <= 4) // 4 == MAX_COM_PORTS + if (BaudRate == 0) + BaudRate = DEFAULT_BAUD_RATE; + + if (ComPort == 0) + { + /* + * Start enumerating COM ports from the last one to the first one, + * and break when we find a valid port. + * If we reach the first element of the list, the invalid COM port, + * then it means that no valid port was found. + */ + for (ComPort = MAX_COM_PORTS; ComPort > 0; ComPort--) { if (CpDoesPortExist(UlongToPtr(BaseArray[ComPort]))) { Address = UlongToPtr(BaseArray[ComPort]); - } - else - { - return FALSE; + break; } } - else - { + if (ComPort == 0) return FALSE; - } - - Status = CpInitialize(&Rs232ComPort, Address, BaudRate); - if (!NT_SUCCESS(Status)) return FALSE; - - PortInitialized = TRUE; } + else if (ComPort <= MAX_COM_PORTS) + { + if (CpDoesPortExist(UlongToPtr(BaseArray[ComPort]))) + Address = UlongToPtr(BaseArray[ComPort]); + else + return FALSE; + } + else + { + return FALSE; + } + + Status = CpInitialize(&Rs232ComPortInfo, Address, BaudRate); + if (!NT_SUCCESS(Status)) return FALSE; + + Rs232ComPort = ComPort; return TRUE; } BOOLEAN Rs232PortGetByte(PUCHAR ByteReceived) { - if (PortInitialized == FALSE) - return FALSE; - - return (CpGetByte(&Rs232ComPort, ByteReceived, TRUE, FALSE) == CP_GET_SUCCESS); + if (Rs232ComPort == 0) return FALSE; + return (CpGetByte(&Rs232ComPortInfo, ByteReceived, TRUE, FALSE) == CP_GET_SUCCESS); } /* BOOLEAN Rs232PortPollByte(PUCHAR ByteReceived) { - if (PortInitialized == FALSE) - return FALSE; - - return (CpGetByte(&Rs232ComPort, ByteReceived, FALSE, FALSE) == CP_GET_SUCCESS); + if (Rs232ComPort == 0) return FALSE; + return (CpGetByte(&Rs232ComPortInfo, ByteReceived, FALSE, FALSE) == CP_GET_SUCCESS); } */ VOID Rs232PortPutByte(UCHAR ByteToSend) { - if (PortInitialized == FALSE) - return; - - CpPutByte(&Rs232ComPort, ByteToSend); + if (Rs232ComPort == 0) return; + CpPutByte(&Rs232ComPortInfo, ByteToSend); } #endif /* DBG */ @@ -126,7 +132,7 @@ VOID Rs232PortPutByte(UCHAR ByteToSend) BOOLEAN Rs232PortInUse(PUCHAR Base) { #if DBG - return ( (PortInitialized && (Rs232ComPort.Address == Base)) ? TRUE : FALSE ); + return ( ((Rs232ComPort != 0) && (Rs232ComPortInfo.Address == Base)) ? TRUE : FALSE ); #else return FALSE; #endif diff --git a/reactos/boot/freeldr/freeldr/debug.c b/reactos/boot/freeldr/freeldr/debug.c index 48e3bbcdddb..2855f4e27cc 100644 --- a/reactos/boot/freeldr/freeldr/debug.c +++ b/reactos/boot/freeldr/freeldr/debug.c @@ -18,7 +18,6 @@ */ #include - #include #if DBG && !defined(_M_ARM) @@ -33,36 +32,31 @@ #define DBG_DEFAULT_LEVELS (ERR_LEVEL|FIXME_LEVEL) +static UCHAR DbgChannels[DBG_CHANNELS_COUNT]; + #define SCREEN 1 #define RS232 2 #define BOCHS 4 -#define COM1 1 -#define COM2 2 -#define COM3 3 -#define COM4 4 - -#define BOCHS_OUTPUT_PORT 0xe9 - -static UCHAR DbgChannels[DBG_CHANNELS_COUNT]; +#define BOCHS_OUTPUT_PORT 0xE9 ULONG DebugPort = RS232; -// ULONG DebugPort = SCREEN; -// ULONG DebugPort = BOCHS; -// ULONG DebugPort = SCREEN|BOCHS; -#ifdef _WINKD_ -/* COM1 is the WinDbg port */ -ULONG ComPort = COM2; -#else -ULONG ComPort = COM1; -#endif -// ULONG BaudRate = 19200; + +/* Serial debug connection */ +ULONG ComPort = 0; // The COM port initializer chooses the first available port starting from COM4 down to COM1. ULONG BaudRate = 115200; +ULONG PortIrq = 0; // Not used at the moment. BOOLEAN DebugStartOfLine = TRUE; -VOID DebugInit(VOID) +VOID DebugInit(BOOLEAN MainInit) { + PCHAR CommandLine, PortString, BaudString, IrqString; + ULONG Value; + CHAR DebugString[256]; + + /* Always reset the debugging channels */ + #if defined (DEBUG_ALL) memset(DbgChannels, MAX_LEVEL, DBG_CHANNELS_COUNT); #elif defined (DEBUG_WARN) @@ -83,9 +77,121 @@ VOID DebugInit(VOID) DbgChannels[DPRINT_WINDOWS] = MAX_LEVEL; #endif + /* Check for pre- or main initialization phase */ + if (!MainInit) + { + /* Pre-initialization phase: use the FreeLdr command-line debugging string */ + CommandLine = (PCHAR)CmdLineGetDebugString(); + + /* If no command-line is provided, initialize the debug port with default settings */ + if (CommandLine == NULL) + goto Done; + + strcpy(DebugString, CommandLine); + } + else + { + /* Main initialization phase: use the FreeLdr INI debugging string */ + + ULONG_PTR SectionId; + + if (!IniOpenSection("FreeLoader", &SectionId)) + return; + + if (!IniReadSettingByName(SectionId, "Debug", DebugString, sizeof(DebugString))) + return; + } + + /* Get the Command Line */ + CommandLine = DebugString; + + /* Upcase it */ + _strupr(CommandLine); + + /* Get the port and baud rate */ + PortString = strstr(CommandLine, "DEBUGPORT"); + BaudString = strstr(CommandLine, "BAUDRATE"); + IrqString = strstr(CommandLine, "IRQ"); + + /* + * Check if we got /DEBUGPORT parameters. + * NOTE: Inspired by reactos/ntoskrnl/kd/kdinit.c, KdInitSystem(...) + */ + while (PortString) + { + /* Move past the actual string, to reach the port*/ + PortString += strlen("DEBUGPORT"); + + /* Now get past any spaces and skip the equal sign */ + while (*PortString == ' ') PortString++; + PortString++; + + /* Check for possible ports and set the port to use */ + if (strncmp(PortString, "SCREEN", 6) == 0) + { + PortString += 6; + DebugPort |= SCREEN; + } + else if (strncmp(PortString, "BOCHS", 5) == 0) + { + PortString += 5; + DebugPort |= BOCHS; + } + else if (strncmp(PortString, "COM", 3) == 0) + { + PortString += 3; + DebugPort |= RS232; + + /* Set the port to use */ + Value = atol(PortString); + if (Value) ComPort = Value; + } + + PortString = strstr(PortString, "DEBUGPORT"); + } + + /* Check if we got a baud rate */ + if (BaudString) + { + /* Move past the actual string, to reach the rate */ + BaudString += strlen("BAUDRATE"); + + /* Now get past any spaces */ + while (*BaudString == ' ') BaudString++; + + /* And make sure we have a rate */ + if (*BaudString) + { + /* Read and set it */ + Value = atol(BaudString + 1); + if (Value) BaudRate = Value; + } + } + + /* Check Serial Port Settings [IRQ] */ + if (IrqString) + { + /* Move past the actual string, to reach the rate */ + IrqString += strlen("IRQ"); + + /* Now get past any spaces */ + while (*IrqString == ' ') IrqString++; + + /* And make sure we have an IRQ */ + if (*IrqString) + { + /* Read and set it */ + Value = atol(IrqString + 1); + if (Value) PortIrq = Value; + } + } + +Done: + /* Try to initialize the port; if it fails, remove the corresponding flag */ if (DebugPort & RS232) { - Rs232PortInitialize(ComPort, BaudRate); + if (!Rs232PortInitialize(ComPort, BaudRate)) + DebugPort &= ~RS232; } } @@ -114,9 +220,9 @@ VOID DebugPrintChar(UCHAR Character) ULONG DbgPrint(const char *Format, ...) { - int i; - int Length; va_list ap; + int Length; + char* ptr; CHAR Buffer[512]; va_start(ap, Format); @@ -133,10 +239,9 @@ DbgPrint(const char *Format, ...) Length = sizeof(Buffer); } - for (i = 0; i < Length; i++) - { - DebugPrintChar(Buffer[i]); - } + ptr = Buffer; + while (Length--) + DebugPrintChar(*ptr++); return 0; } @@ -149,7 +254,7 @@ DbgPrint2(ULONG Mask, ULONG Level, const char *File, ULONG Line, char *Format, . char *ptr = Buffer; /* Mask out unwanted debug messages */ - if (!(DbgChannels[Mask] & Level) && !(Level & DBG_DEFAULT_LEVELS )) + if (!(DbgChannels[Mask] & Level) && !(Level & DBG_DEFAULT_LEVELS)) { return; } @@ -191,9 +296,8 @@ DbgPrint2(ULONG Mask, ULONG Level, const char *File, ULONG Line, char *Format, . VOID DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length) { - PUCHAR BufPtr = (PUCHAR)Buffer; - ULONG Idx; - ULONG Idx2; + PUCHAR BufPtr = (PUCHAR)Buffer; + ULONG Idx, Idx2; /* Mask out unwanted debug messages */ if (!(DbgChannels[Mask] & TRACE_LEVEL)) @@ -202,7 +306,7 @@ DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length) DebugStartOfLine = FALSE; // We don't want line headers DbgPrint("Dumping buffer at %p with length of %lu bytes:\n", Buffer, Length); - for (Idx=0; Idx 20) && (BufPtr[Idx] < 0x80)) { @@ -257,10 +361,10 @@ DbgAddDebugChannel(CHAR* channel, CHAR* level, CHAR op) { int iLevel, iChannel; - if (channel == NULL || *channel == L'\0' || strlen(channel) == 0 ) + if (channel == NULL || *channel == '\0' || strlen(channel) == 0) return FALSE; - if (level == NULL || *level == L'\0' || strlen(level) == 0 ) + if (level == NULL || *level == '\0' || strlen(level) == 0) iLevel = MAX_LEVEL; else if (strcmp(level, "err") == 0) iLevel = ERR_LEVEL; @@ -290,9 +394,9 @@ DbgAddDebugChannel(CHAR* channel, CHAR* level, CHAR op) { int i; - for(i= 0 ; i < DBG_CHANNELS_COUNT; i++) + for (i = 0; i < DBG_CHANNELS_COUNT; i++) { - if(op==L'+') + if (op == '+') DbgChannels[i] |= iLevel; else DbgChannels[i] &= ~iLevel; @@ -302,7 +406,7 @@ DbgAddDebugChannel(CHAR* channel, CHAR* level, CHAR op) } else return FALSE; - if (op == L'+') + if (op == '+') DbgChannels[iChannel] |= iLevel; else DbgChannels[iChannel] &= ~iLevel; diff --git a/reactos/boot/freeldr/freeldr/freeldr.c b/reactos/boot/freeldr/freeldr/freeldr.c index d6bcaa8c6a0..7c7ee14e02b 100644 --- a/reactos/boot/freeldr/freeldr/freeldr.c +++ b/reactos/boot/freeldr/freeldr/freeldr.c @@ -26,19 +26,21 @@ DBG_DEFAULT_CHANNEL(WARNING); /* FUNCTIONS ******************************************************************/ -VOID __cdecl BootMain(LPSTR CmdLine) +VOID __cdecl BootMain(IN PCCH CmdLine) { CmdLineParse(CmdLine); MachInit(CmdLine); FsInit(); - DebugInit(); + /* Debugger pre-initialization */ + DebugInit(FALSE); TRACE("BootMain() called.\n"); /* Check if the CPU is new enough */ FrLdrCheckCpuCompatiblity(); + /* UI pre-initialization */ if (!UiInitialize(FALSE)) { UiMessageBoxCritical("Unable to initialize UI."); diff --git a/reactos/boot/freeldr/freeldr/include/cmdline.h b/reactos/boot/freeldr/freeldr/include/cmdline.h index 68f61a11a3c..3ab13c21fdc 100644 --- a/reactos/boot/freeldr/freeldr/include/cmdline.h +++ b/reactos/boot/freeldr/freeldr/include/cmdline.h @@ -19,8 +19,9 @@ #pragma once -VOID CmdLineParse(IN PCHAR CmdLine); +VOID CmdLineParse(IN PCCH CmdLine); +PCCH CmdLineGetDebugString(VOID); PCCH CmdLineGetDefaultOS(VOID); LONG CmdLineGetTimeOut(VOID); diff --git a/reactos/boot/freeldr/freeldr/include/debug.h b/reactos/boot/freeldr/freeldr/include/debug.h index be0d906cee8..9cf62ebb8ee 100644 --- a/reactos/boot/freeldr/freeldr/include/debug.h +++ b/reactos/boot/freeldr/freeldr/include/debug.h @@ -40,7 +40,7 @@ #if DBG && !defined(_M_ARM) - VOID DebugInit(VOID); + VOID DebugInit(BOOLEAN MainInit); ULONG DbgPrint(const char *Format, ...); VOID DbgPrint2(ULONG Mask, ULONG Level, const char *File, ULONG Line, char *Format, ...); VOID DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length); @@ -113,7 +113,7 @@ void MEMORY_WRITE_BREAKPOINT4(unsigned long addr); #define UNIMPLEMENTED - #define DebugInit() + #define DebugInit(init) #define BugCheck(fmt, ...) #define DbgDumpBuffer(mask, buf, len) #define DbgParseDebugChannels(val) diff --git a/reactos/boot/freeldr/freeldr/include/freeldr.h b/reactos/boot/freeldr/freeldr/include/freeldr.h index d96d4000394..0bdc9988655 100644 --- a/reactos/boot/freeldr/freeldr/include/freeldr.h +++ b/reactos/boot/freeldr/freeldr/include/freeldr.h @@ -119,7 +119,7 @@ #include #endif -VOID __cdecl BootMain(LPSTR CmdLine); +VOID __cdecl BootMain(IN PCCH CmdLine); VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem); VOID RunLoader(VOID); VOID FrLdrCheckCpuCompatiblity(VOID);