Skip to content

Commit

Permalink
boot: Translate X-codes to C code for basic system initialization
Browse files Browse the repository at this point in the history
Drop using proprietary X-code interpreter & translate X-codes to C code.
This makes it possible to use a southbridge (e.g. MCPX X2) that does not
contain such interpreter.
  • Loading branch information
haxar committed Feb 6, 2021
1 parent b5e315e commit 6efa5d6
Show file tree
Hide file tree
Showing 5 changed files with 306 additions and 111 deletions.
275 changes: 267 additions & 8 deletions boot_rom/2bBootStartBios.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
#include "2bload.h"
#include "sha1.h"

extern int decompress_kernel(char*out, char *data, int len);
extern int decompress_kernel(char *out, char *data, int len);

u32 PciWriteDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int dw)
{

u32 base_addr = 0x80000000;
base_addr |= ((bus & 0xFF) << 16); // bus #
base_addr |= ((dev & 0x1F) << 11); // device #
Expand All @@ -39,13 +38,271 @@ u32 PciReadDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned
base_addr |= ((bus & 0xFF) << 16); // bus #
base_addr |= ((dev & 0x1F) << 11); // device #
base_addr |= ((func & 0x07) << 8); // func #
base_addr |= ((func & 0x07) << 8);
base_addr |= ((reg_off & 0xff));

base_addr |= ((reg_off & 0xff));

IoOutputDword(0xcf8, base_addr);
return IoInputDword(0xcfc);
}

void BootSystemInitialization(void)
{
register u32 res;

/* translated to C from Xcodes.h */
PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x84, 0x00008001);
PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x10, 0x00008001);
PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x04, 0x00000003);
IoOutputByte(0x8049, 0x08);
IoOutputByte(0x80d9, 0x00);
IoOutputByte(0x8026, 0x01);
PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x4c, 0x00000001);
PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x18, 0x00010100);
PciWriteDword(BUS_0, DEV_0, FUNC_0, 0x84, 0x07ffffff);
PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x20, 0x0ff00f00);
PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x24, 0xf7f0f000);
PciWriteDword(BUS_1, DEV_0, FUNC_0, 0x10, 0x0f000000);
PciWriteDword(BUS_1, DEV_0, FUNC_0, 0x14, 0xf0000000);
PciWriteDword(BUS_1, DEV_0, FUNC_0, 0x04, 0x00000007);
PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x04, 0x00000007);
#ifndef MCPXREVD5
writel(0x07633461, 0x0f0010b0);
#else
writel(0x01000010, 0x0f0010b0);
#endif
writel(0x66660000, 0x0f0010cc);
res = readl(0x0f101000);
res &= 0x000c0000;
if (res == 0x00000000) {
res = readl(0x0f101000);
res &= 0xe1f3ffff;
res |= 0x80000000;
writel(res, 0x0f101000);
writel(0xeeee0000, 0x0f0010b8);
} else if (res == 0x000c0000) {
res = readl(0x0f101000);
res &= 0xe1f3ffff;
res |= 0x860c0000;
writel(res, 0x0f101000);
writel(0xffff0000, 0x0f0010b8);
} else {
res = readl(0x0f101000);
res &= 0xe1f3ffff;
res |= 0x820c0000;
writel(res, 0x0f101000);
writel(0x11110000, 0x0f0010b8);
}
writel(0x00000009, 0x0f0010d4);
writel(0x00000000, 0x0f0010b4);
writel(0x00005866, 0x0f0010bc);
writel(0x0351c858, 0x0f0010c4);
writel(0x30007d67, 0x0f0010c8);
writel(0x00000000, 0x0f0010d8);
writel(0xa0423635, 0x0f0010dc);
writel(0x0c6558c6, 0x0f0010e8);
writel(0x03070103, 0x0f100200);
writel(0x11000016, 0x0f100410);
writel(0x84848888, 0x0f100330);
writel(0xffffcfff, 0x0f10032c);
writel(0x00000001, 0x0f100328);
writel(0x000000df, 0x0f100338);

/* initialize SMBus controller */
PciWriteDword(BUS_0, DEV_1, FUNC_1, 0x04, 0x00000001);
PciWriteDword(BUS_0, DEV_1, FUNC_1, 0x14, 0x0000c001);
PciWriteDword(BUS_0, DEV_1, FUNC_1, 0x18, 0x0000c201);
IoOutputByte(SMBUS+0x200, 0x70);

/* initialize video encoder */
/*
* It is necessary to write to the video encoder, as the PIC
* snoops the I2C traffic and will reset us if it doesn't see what
* it judges as 'appropriate' traffic. Conexant is the most urgent,
* as on v1.0 Xboxes, the PIC was very strict and reset us earlier
* than later models.
*/
do {
/* Conexant video encoder */
IoOutputByte(SMBUS+4, 0x8a); /* set Conexant address */
IoOutputByte(SMBUS+8, 0xba);
IoOutputByte(SMBUS+6, 0x3f);
IoOutputByte(SMBUS+2, 0x0a);
do {
res = IoInputByte(SMBUS);
if (res == 0x10) {
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+8, 0x6c);
IoOutputByte(SMBUS+6, 0x46);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+8, 0xb8);
IoOutputByte(SMBUS+6, 0x00);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+8, 0xce);
IoOutputByte(SMBUS+6, 0x19);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+8, 0xc6);
IoOutputByte(SMBUS+6, 0x9c);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+8, 0x32);
IoOutputByte(SMBUS+6, 0x08);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+8, 0xc4);
IoOutputByte(SMBUS+6, 0x01);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
break;
}
} while (res & 0x08);

if (res == 0x10) break;

/* Focus video encoder */
IoOutputByte(SMBUS, 0xff); /* clear any error */
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+4, 0xd4); /* set Focus address */
IoOutputByte(SMBUS+8, 0x0c);
IoOutputByte(SMBUS+6, 0x00);
IoOutputByte(SMBUS+2, 0x0a);
do {
res = IoInputByte(SMBUS);
if (res == 0x10) {
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+8, 0x0d);
IoOutputByte(SMBUS+6, 0x20);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
break;
}
} while (res & 0x08);

if (res == 0x10) break;

/* Xcalibur video encoder */
/*
* We don't check to see if these writes fail, as
* we've already tried Conexant and Focus - Oh dear,
* not another encoder... :(
*/
IoOutputByte(SMBUS, 0xff); /* clear any error */
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+4, 0xe0); /* set Xcalibur address */
IoOutputByte(SMBUS+8, 0x00);
IoOutputByte(SMBUS+6, 0x00);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+8, 0xb8);
IoOutputByte(SMBUS+6, 0x00);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
} while (0);

IoOutputByte(SMBUS+4, 0x20); /* set PIC write address */
IoOutputByte(SMBUS+8, 0x01);
IoOutputByte(SMBUS+6, 0x00);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+4, 0x21); /* set PIC read address */
IoOutputByte(SMBUS+8, 0x01);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
res = IoInputByte(SMBUS+6); /* if SMC version does not match ... ????? */
writel(0x00011c01, 0x0f680500);
writel(0x000a0400, 0x0f68050c);
writel(0x00000000, 0x0f001220);
writel(0x00000000, 0x0f001228);
writel(0x00000000, 0x0f001264);
writel(0x00000010, 0x0f001210);
res = readl(0x0f101000);
res &= 0x06000000;
if (res == 0x00000000) {
writel(0x48480848, 0x0f001214);
writel(0x88888888, 0x0f00122c);
} else {
writel(0x09090909, 0x0f001214);
writel(0xaaaaaaaa, 0x0f00122c);
}
writel(0xffffffff, 0x0f001230);
writel(0xaaaaaaaa, 0x0f001234);
writel(0xaaaaaaaa, 0x0f001238);
writel(0x8b8b8b8b, 0x0f00123c);
writel(0xffffffff, 0x0f001240);
writel(0x8b8b8b8b, 0x0f001244);
writel(0x8b8b8b8b, 0x0f001248);
writel(0x00000001, 0x0f1002d4);
writel(0x00100042, 0x0f1002c4);
writel(0x00100042, 0x0f1002cc);
writel(0x00000011, 0x0f1002c0);
writel(0x00000011, 0x0f1002c8);
writel(0x00000032, 0x0f1002c0);
writel(0x00000032, 0x0f1002c8);
writel(0x00000132, 0x0f1002c0);
writel(0x00000132, 0x0f1002c8);
writel(0x00000001, 0x0f1002d0);
writel(0x00000001, 0x0f1002d0);
writel(0x80000000, 0x0f100210);
writel(0xaa8baa8b, 0x0f00124c);
writel(0x0000aa8b, 0x0f001250);
writel(0x081205ff, 0x0f100228);
writel(0x00010000, 0x0f001218);
res = PciReadDword(BUS_0, DEV_1, FUNC_0, 0x60);
res |= 0x00000400;
PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x60, res);
PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x4c, 0x0000fdde);
PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x9c, 0x871cc707);
res = PciReadDword(BUS_0, DEV_1, FUNC_0, 0xb4);
res |= 0x00000f00;
PciWriteDword(BUS_0, DEV_1, FUNC_0, 0xb4, res);
PciWriteDword(BUS_0, DEV_0, FUNC_3, 0x40, 0xf0f0c0c0);
PciWriteDword(BUS_0, DEV_0, FUNC_3, 0x44, 0x00c00000);
PciWriteDword(BUS_0, DEV_0, FUNC_3, 0x5c, 0x04070000);
PciWriteDword(BUS_0, DEV_0, FUNC_3, 0x6c, 0x00230801);
PciWriteDword(BUS_0, DEV_0, FUNC_3, 0x6c, 0x01230801);
writel(0x03070103, 0x0f100200);
writel(0x11448000, 0x0f100204);
PciWriteDword(BUS_0, DEV_2, FUNC_0, 0x3c, 0x00000000);
IoOutputByte(SMBUS, 0x10);

/* report memory size to PIC scratch register */
IoOutputByte(SMBUS+4, 0x20); /* set PIC write address */
IoOutputByte(SMBUS+8, 0x13);
IoOutputByte(SMBUS+6, 0x0f);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);
IoOutputByte(SMBUS+8, 0x12);
IoOutputByte(SMBUS+6, 0xf0);
IoOutputByte(SMBUS+2, 0x0a);
while (IoInputByte(SMBUS) != 0x10);
IoOutputByte(SMBUS, 0x10);

/* reload NV2A registers */
PciWriteDword(BUS_0, DEV_1e, FUNC_0, 0x20, 0xfdf0fd00);
PciWriteDword(BUS_1, DEV_0, FUNC_0, 0x10, 0xfd000000);

IoOutputByte(0x0061, 0x08);

/* enable IDE and NIC */
PciWriteDword(BUS_0, DEV_1, FUNC_0, 0x8c, 0x40000000);

/* CPU whoami ? sesless ? */
PciWriteDword(BUS_0, DEV_0, FUNC_0, 0x80, 0x00000100);
}

void BootAGPBUSInitialization(void)
{
u32 temp;
Expand All @@ -58,9 +315,8 @@ void BootAGPBUSInitialization(void)
IoOutputDword(0xcfc , temp );

PciWriteDword(BUS_0, DEV_0, FUNC_0, 0x80, 0x00000100);

}

/* ------------------------- Main Entry for after the ASM sequences ------------------------ */

extern void BootStartBiosLoader ( void ) {
Expand All @@ -86,7 +342,10 @@ extern void BootStartBiosLoader ( void ) {
unsigned int Biossize_type;

int validimage;


// Perform basic system initialization (formerly from X-codes)
BootSystemInitialization();

memcpy(&bootloaderChecksum[0],(void*)PROGRAMM_Memory_2bl,20);
memcpy(&bootloadersize,(void*)(PROGRAMM_Memory_2bl+20),4);
memcpy(&compressed_image_start,(void*)(PROGRAMM_Memory_2bl+24),4);
Expand Down
44 changes: 13 additions & 31 deletions boot_rom/2bBootStartup.S
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
Xcalibur support by Lehner Franz ([email protected])
*/

#include "2bconsts.h"
#include "consts.h"

#define xcode_peek(val1) .byte 0x2; .long val1 ; .long 0x0 ;
#define xcode_poke(val1,val2) .byte 0x3; .long val1 ; .long val2 ;
Expand All @@ -45,9 +45,6 @@

#define xcode_END(val1) .byte 0xEE; .long val1 ; .long 0x0;

#define SMBUS 0x0000c000


#define SMB_xcode_Write(val1,val2); xcode_outb(SMBUS+8, val1); \
xcode_outb(SMBUS+6, val2); \
xcode_outb(SMBUS+2, 0x0000000a); \
Expand Down Expand Up @@ -106,7 +103,14 @@

//The bytecode interpreter begins here
.org 0x80
#include "Xcodes.h"

// Note: X-codes are now translated to C code in BootSystemInitialization()

// overflow trick
xcode_poke(0x00000000, 0xfc1000ea);
xcode_poke(0x00000004, 0x000008ff);

xcode_END(0x806);

// Note: never change this from offset 0x1000 ....
// This is the Main Entry point ....
Expand Down Expand Up @@ -338,31 +342,9 @@ reload_cs:
xor %eax, %eax
mov %eax, %fs
mov %eax, %gs

movl $ 0x1ffff0,%esp

mov $0x8, %al
mov $0x61, %dx
out %al, %dx

// Enable IDE and NIC
mov $0x8000088C, %eax
movw $0xcf8, %dx
outl %eax, %dx
movw $0xcfc, %dx
movl $0x40000000, %eax
outl %eax, %dx


// CPU Whoami ? sesless ?
mov $0x80000080, %eax
movw $0xcf8, %dx
outl %eax, %dx
movw $0xcfc, %dx
movl $0x100, %eax
outl %eax, %dx


movl $0x1ffff0, %esp

// this can be found in BootResetAction.c
jmp BootStartBiosLoader
jmp BootStartBiosLoader

Loading

0 comments on commit 6efa5d6

Please sign in to comment.