Author: mcayland
Date: Mon Aug 19 09:40:12 2013
New Revision: 1209
URL: http://tracker.coreboot.org/trac/openbios/changeset/1209
Log:
SPARC32: fix romvec stdin/stdout field initialisation
Previously the romvec stdin/stdout ihandles were configured so that they were
set to the current stdin and stdout paths at initialisation time. Unfortunately
as stdin/stdout can be changed with the input and output words, they can end
up pointing to invalid ihandles causing a crash when trying to output to the
console.
Fix this by pointing the romvec structure to the address of the stdin/stdout
variables so that they are always in sync. Similarly we also resolve the
text path stdin/stdout variables at boot time to ensure that they will never
be stale.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland(a)ilande.co.uk>
Modified:
trunk/openbios-devel/arch/sparc32/boot.c
trunk/openbios-devel/arch/sparc32/romvec.c
Modified: trunk/openbios-devel/arch/sparc32/boot.c
==============================================================================
--- trunk/openbios-devel/arch/sparc32/boot.c Mon Aug 19 09:40:10 2013 (r1208)
+++ trunk/openbios-devel/arch/sparc32/boot.c Mon Aug 19 09:40:12 2013 (r1209)
@@ -23,7 +23,7 @@
void go(void)
{
ucell address, type, size;
- int image_retval = 0, proplen, target, device;
+ int image_retval = 0, intprop, proplen, target, device;
phandle_t chosen;
char *prop, *id, *name;
static char bootpathbuf[128], bootargsbuf[128], buf[128];
@@ -40,8 +40,19 @@
needs to be set up to pass certain parameters using a C struct. Hence this section
extracts the relevant boot information and places it in obp_arg. */
- /* Get the name of the selected boot device, along with the device and unit number */
+ /* Get the stdin and stdout paths */
chosen = find_dev("/chosen");
+ intprop = get_int_property(chosen, "stdin", &proplen);
+ PUSH(intprop);
+ fword("get-instance-path");
+ ((struct linux_romvec *)romvec)->pv_stdin = pop_fstr_copy();
+
+ intprop = get_int_property(chosen, "stdout", &proplen);
+ PUSH(intprop);
+ fword("get-instance-path");
+ ((struct linux_romvec *)romvec)->pv_stdout = pop_fstr_copy();
+
+ /* Get the name of the selected boot device, along with the device and unit number */
prop = get_property(chosen, "bootpath", &proplen);
strncpy(bootpathbuf, prop, proplen);
prop = get_property(chosen, "bootargs", &proplen);
Modified: trunk/openbios-devel/arch/sparc32/romvec.c
==============================================================================
--- trunk/openbios-devel/arch/sparc32/romvec.c Mon Aug 19 09:40:10 2013 (r1208)
+++ trunk/openbios-devel/arch/sparc32/romvec.c Mon Aug 19 09:40:12 2013 (r1209)
@@ -25,7 +25,6 @@
#endif
char obp_stdin, obp_stdout;
-static int obp_fd_stdin, obp_fd_stdout;
const char *obp_stdin_path, *obp_stdout_path;
struct linux_arguments_v0 obp_arg;
@@ -498,15 +497,12 @@
romvec0.pv_v2bootargs.bootpath = &bootpath;
romvec0.pv_v2bootargs.bootargs = &obp_arg.argv[1];
- romvec0.pv_v2bootargs.fd_stdin = &obp_fd_stdin;
- romvec0.pv_v2bootargs.fd_stdout = &obp_fd_stdout;
- push_str(obp_stdin_path);
- fword("open-dev");
- obp_fd_stdin = POP();
- push_str(obp_stdout_path);
- fword("open-dev");
- obp_fd_stdout = POP();
+ /* Point fd_stdin/fd_stdout to the Forth stdin/stdout variables */
+ fword("stdin");
+ romvec0.pv_v2bootargs.fd_stdin = cell2pointer(POP());
+ fword("stdout");
+ romvec0.pv_v2bootargs.fd_stdout = cell2pointer(POP());
romvec0.v3_memalloc = obp_memalloc_handler;
This patch corrects two long-standing bugs with PPC PCI configuration space
access. Firstly fix the calculation of PCI configuration space addresses by
the PCI_ADDR macro; this was incorrectly using arch->cfg_base which is the
mapped address and has nothing to do with the PCI configuration space
address. Instead just set bit 31 to initiate a configuration cycle as per the
PCI specification.
Secondly, fix pci_config_read32() and pci_config_write16() which were
incorrectly adding the register offset to the PCI IO dataport address causing
them to write into unknown address space for registers > 0. It appears that
this only worked purely by coincidence with QEMU due to the way in which the
configuration address was calculated for an oversized PCI configuration IO
dataport MemoryRegion.
Reported-by: Hervé Poussineau <hpoussin(a)reactos.org>
CC: Hervé Poussineau <hpoussin(a)reactos.org>
CC: Andreas Färber <afaerber(a)suse.de>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland(a)ilande.co.uk>
---
openbios-devel/include/arch/ppc/pci.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/openbios-devel/include/arch/ppc/pci.h b/openbios-devel/include/arch/ppc/pci.h
index cccefb1..d96bd7e 100644
--- a/openbios-devel/include/arch/ppc/pci.h
+++ b/openbios-devel/include/arch/ppc/pci.h
@@ -12,7 +12,7 @@
/* PCI Configuration Mechanism #1 */
#define PCI_ADDR(bus, dev, fn) \
- ((pci_addr) (arch->cfg_base \
+ ((pci_addr) (0x80000000u \
| (uint32_t) (bus) << 16 \
| (uint32_t) (dev) << 11 \
| (uint32_t) (fn) << 8))
@@ -41,7 +41,7 @@ static inline uint32_t pci_config_read32(pci_addr dev, uint8_t reg)
{
uint32_t res;
out_le32((unsigned *)arch->cfg_addr, dev | reg);
- res = in_le32((unsigned *)(arch->cfg_data + reg));
+ res = in_le32((unsigned *)(arch->cfg_data));
return res;
}
@@ -60,7 +60,7 @@ static inline void pci_config_write16(pci_addr dev, uint8_t reg, uint16_t val)
static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val)
{
out_le32((unsigned *)arch->cfg_addr, dev | reg);
- out_le32((unsigned *)(arch->cfg_data + reg), val);
+ out_le32((unsigned *)(arch->cfg_data), val);
}
#else /* !PCI_CONFIG_1 */
#error PCI Configuration Mechanism is not specified or implemented
--
1.7.10.4
Author: mcayland
Date: Mon Sep 2 15:45:56 2013
New Revision: 1225
URL: http://tracker.coreboot.org/trac/openbios/changeset/1225
Log:
PPC: Fix PCI configuration space address access
This patch corrects two long-standing bugs with PPC PCI configuration space
access. Firstly fix the calculation of PCI configuration space addresses by
the PCI_ADDR macro; this was incorrectly using arch->cfg_base which is the
mapped address and has nothing to do with the PCI configuration space
address. Instead just set bit 31 to initiate a configuration cycle as per the
PCI specification.
Secondly, fix pci_config_read32() and pci_config_write32() which were
incorrectly adding the register offset to the PCI IO dataport address causing
them to write into unknown address space for registers > 0. It appears that
this only worked purely by coincidence with QEMU due to the way in which the
configuration address was calculated for an oversized PCI configuration IO
dataport MemoryRegion.
Reported-by: Hervé Poussineau <hpoussin(a)reactos.org>
CC: Hervé Poussineau <hpoussin(a)reactos.org>
CC: Andreas Färber <afaerber(a)suse.de>
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland(a)ilande.co.uk>
Modified:
trunk/openbios-devel/include/arch/ppc/pci.h
Modified: trunk/openbios-devel/include/arch/ppc/pci.h
==============================================================================
--- trunk/openbios-devel/include/arch/ppc/pci.h Sat Aug 24 22:00:36 2013 (r1224)
+++ trunk/openbios-devel/include/arch/ppc/pci.h Mon Sep 2 15:45:56 2013 (r1225)
@@ -12,7 +12,7 @@
/* PCI Configuration Mechanism #1 */
#define PCI_ADDR(bus, dev, fn) \
- ((pci_addr) (arch->cfg_base \
+ ((pci_addr) (0x80000000u \
| (uint32_t) (bus) << 16 \
| (uint32_t) (dev) << 11 \
| (uint32_t) (fn) << 8))
@@ -41,7 +41,7 @@
{
uint32_t res;
out_le32((unsigned *)arch->cfg_addr, dev | reg);
- res = in_le32((unsigned *)(arch->cfg_data + reg));
+ res = in_le32((unsigned *)(arch->cfg_data));
return res;
}
@@ -60,7 +60,7 @@
static inline void pci_config_write32(pci_addr dev, uint8_t reg, uint32_t val)
{
out_le32((unsigned *)arch->cfg_addr, dev | reg);
- out_le32((unsigned *)(arch->cfg_data + reg), val);
+ out_le32((unsigned *)(arch->cfg_data), val);
}
#else /* !PCI_CONFIG_1 */
#error PCI Configuration Mechanism is not specified or implemented