It/Porting an Operating System to the Xbox HOWTO
From Xbox-Linux
|
Il sito di Xbox-Linux e disponibile anche in: English |
di Michael Steil traduzione ad opera di SeV3n
Xbox può essere considerata come un computer compatibile con IBM PC a basso costo (149 DOLLARI/EURO), per questo motivo può essere utilizzata come server, come workstation o come lettore multimediale. Per via di piccole differenze dal punto di vista dell' hardware, affinchè i sistemi operativi siano compatibili con Xbox, è necessario effettuare alcune modifiche software.
Questo documento descrive in dettaglio le succitate differenze, illustra come gestirle nel vostro sistema operativo e come cominciare.
| Table of contents |
Individuare una Xbox
Non c'è alcun bisogno di costruire un kernel personalizzato specificamente per Xbox dal momento che, come già detto, quest'ultima è molto simile a un comune PC. Per stabilire se la macchina su cui l'OS sta per partire è o meno una Xbox è sufficiente inserire una stringa di codice specifica per Xbox "if(machine_is_xbox) {...}". Il modo più semplice per sapere se ci troviamo su una Xbox è questo:
outl(0x80000000, 0xcf8);
if (inl(0xcfc)==0x02a510de) { /* Xbox PCI 0:0:0 ID 0x10de/0x02a5 */
machine_is_xbox = 1;
else
machine_is_xbox = 0;
Queste righe di codice controllano l'ID PCI del CPU bridge, che è unico sull'Xbox. Quando inserite questo codice all'interno del vostro kernel, assicuratevi che:
- venga eseguito all'inizio dal momento che le istruzioni successive (vedere sotto) dipenderanno da questa IF.
- queste linee verranno compilate solo su un'architettura x86, quindi, su altre piattaforme, le funzioni outl() e inl() probabilmente interromperebbero il processo o potrebbero risultare nocive se compilate.
Differenze
L'hardware dell'Xbox consiste di componenti standard, quali una CPU Pentium III Celeron, un chipset nFORCE, un DVD IDE e un Hard Disk. Tuttavia ci sono alcune piccole differenze, alcune delle quali farebbero crashare un sistema operativo se non opportunamente modificato.
Chipset
Il chipset dell'Xbox è fondamentalmente un nVidia nForce 420, ma con una un GeForce "NV2a" integrata (anzichè un GeForce2 MX ), e con una CPU Intel al posto di una CPU AMD. Di seguito l'output del "lspci" su un PC equipaggiato di nForce:
00:00.0 Host bridge: nVidia Corporation nForce CPU bridge (rev b2) 00:00.1 RAM memory: nVidia Corporation nForce 220/420 Memory Controller (rev b2) 00:00.2 RAM memory: nVidia Corporation nForce 220/420 Memory Controller (rev b2) 00:00.3 RAM memory: nVidia Corporation nForce 420 Memory Controller (DDR) (rev b2) 00:01.0 ISA bridge: nVidia Corporation nForce ISA Bridge (rev c3) 00:01.1 SMBus: nVidia Corporation nForce PCI System Management (rev c1) 00:02.0 USB Controller: nVidia Corporation nForce USB Controller (rev c3) 00:03.0 USB Controller: nVidia Corporation nForce USB Controller (rev c3) 00:04.0 Ethernet controller: nVidia Corporation nForce Ethernet Controller (rev d2) 00:05.0 Multimedia audio controller: nVidia Corporation: Unknown device 01b0 (rev c2) 00:06.0 Multimedia audio controller: nVidia Corporation nForce Audio (rev c2) 00:08.0 PCI bridge: nVidia Corporation nForce PCI-to-PCI bridge (rev c2) 00:09.0 IDE interface: nVidia Corporation nForce IDE (rev c3) 00:1e.0 PCI bridge: nVidia Corporation nForce AGP to PCI Bridge (rev b2) 02:00.0 VGA compatible controller: nVidia Corporation NVCrush11 [GeForce2 MX Integrated Graphics] (rev b1)
Sull'Xbox l'output somiglia invece a questo:
00:00.0 Host bridge: nVidia Corporation: Unknown device 02a5 (rev a1) 00:00.3 RAM memory: nVidia Corporation: Unknown device 02a6 (rev a1) 00:01.0 ISA bridge: nVidia Corporation nForce ISA Bridge (rev d4) 00:01.1 SMBus: nVidia Corporation nForce PCI System Management (rev d1) 00:02.0 USB Controller: nVidia Corporation nForce USB Controller (rev d4) 00:03.0 USB Controller: nVidia Corporation nForce USB Controller (rev d4) 00:04.0 Ethernet controller: nVidia Corporation nForce Ethernet Controller (rev d2) 00:05.0 Multimedia audio controller: nVidia Corporation: Unknown device 01b0 (rev d2) 00:06.0 Multimedia audio controller: nVidia Corporation nForce Audio (rev d2) 00:06.1 Modem: nVidia Corporation Intel 537 [nForce MC97 Modem] (rev d1) 00:08.0 PCI bridge: nVidia Corporation nForce PCI-to-PCI bridge (rev d2) 00:09.0 IDE interface: nVidia Corporation nForce IDE (rev d4) 00:1e.0 PCI bridge: nVidia Corporation nForce AGP to PCI Bridge (rev a1) 01:00.0 VGA compatible controller: nVidia Corporation: Unknown device 02a0 (rev a1)
Il bus PCI 0 è quasi identico ad eccezione del fatto che l'Xbox possiede un solo controller di memoria. Il bus 1 sul PC contiene tutte le schede PCI. Su Xbox invece il bus 1 coincide con il bus AGP (anzichè con il bus 2) poichè l'Xbox non supporta schede PCI.
Bug dell'enumerazione PCI
Le due differenze del chipset nForce tra la versione PC e quella per Xbox hanno introdotto tre bugs all'interno del chipset che hanno a che vedere con l'enumerazione PCI:
- Gli inesistenti controllers di memoria sullo 0:0.1 e 0:0.2 sono completamente broken: se provate a testarli, per esempio leggendo i loro PCI IDs, l'Xbox freeza.
- Ci sono dei devices fantasma sul bus1 dopo il controller video (1:0.0). Se provate a testarli otterrete solo spazzatura.
- La stessa cosa avviene sul bus 2.
Se il vostro sistema operativo scansiona il bus PCI per stabilire quali drivers debbano essere caricati per i devices PCI, non toccate lo 0:0.1 e lo 0:0.2 . Il modo più semplice per ovviare all'inconveniente sarebbe quello di far cominciare l'enumerazione PCI con 0:1.0 dato che i primi e pochi devices non necessitano di alcun driver. Tuttavia il codice sotto-riportato, preso dall'Xbox Linux kernel, gestisce al meglio questa situazione e nasconde i devices fantasma:
if (mach_pci_is_blacklisted(bus, PCI_SLOT(devfn), PCI_FUNC(devfn)))
return -EINVAL;
static inline int mach_pci_is_blacklisted(int bus, int dev, int fn)
{
if(machine_is_xbox) {
return (bus > 1) || ((bus != 0) && ((dev != 0) || (fn != 0))) ||
(!bus && !dev && ((fn == 1) || (fn == 2)));
}
}
Va sottolineato che alcuni sistemi operativi (o anche qualche applicazione) ripetono l'enumerazione PCI anche in seguito: per esempio, su sistemi Unix, i servers XFree86/X.org e X Window eseguono una seconda enumerazione che può però essere disattivata tramite un parametro di configurazione ( o patchando il codice sorgente).
Niente Controller per la Tastiera
L'Xbox è una sorta di PC free, ciò significa che non contiene il così detto "Super-I/O Chip" che include i vecchi hardware ISA quali:
- porta seriale
- porta parallela
- controller del floppy disk
- controller della tastiera
In generale questo non dovrebbe costituire un problema per alcun sistema operativo; tuttavia c'è da notare una cosa: molti sistemi operativi (come Linux 2.4.x e superiori) danno per scontato che un PC sia dotato di un controller della tastiera (anche se questo non è vero per molti sistemi embedded x86 come i sistemi Itanium ) e per questo motivo allocano staticamente la linea di interrupt 1 per il controller della tastiera.
Il problema è che il codice originale di inizializzazione dell'hardware Xbox ( come il Cromwell) fixa sull'interrupt 1 il primo controller USB, così facendo, se il sistema operativo ha già allocato il primo interrupt, il primo controller USB non funzionerà. Su una Xbox 1.0 questo significa non poter utilizzare alcun device USb (inclusa, ironicamente, una tastiera), mentre sulle versioni suffessive (dalla 1.1 alla 1.6b) il non-funzionamento affligge solo due dei quattro connettori USB.
Fate quindi in modo che il vostro sistema operativo controlli l'esistenza del controller della tastiera e che non allochi alcun interrupt if quest'ultimo non è presente. Il seguente codice, preso dal kernel Linux, mostra come effettuare il checking del controller della tastiera:
#define kbd_read_input() inb(KBD_DATA_REG) #define kbd_read_status() inb(KBD_STATUS_REG) if (kbd_read_status() == 0xff && kbd_read_input() == 0xff) kbd_exists = 0;
Frequenza del Timer
Il timer di sistema all'interno delll'unità "8254 PIT" del chipset nella versione PC ha una frequenza di base pari a 1.193182 MHz. Il numero di task switches, l'orologio di sistema e tutti tutti i timings per le operazioni multimediali sono solitamente basate sugli interrupts generati dall'unità PIT. Per qualche sconosciuta ragione, questa frequenza di base sull'Xbox è pari a 1.125000 MHz, ovvero il 6% più bassa. Se il vostro sistema operativo non amministra questa differenza di frequenza, i file multimediali verranno eseguiti a velocità errate e l'orologio di sistema ( se avete un orologio software e non utilizzate quello hardware) risulterà presto sballato.
Tutto ciò che dovete fare è cercare le ricorrenze della costante 1193182 ( qualche volta è 1193180 ) e sostituirle con il codice seguente:
timer_base = machine_is_xbox? 1125000 : 1193182;
Nel caso in cui il vostro sistema operativo definisca tale frequenza come costante, dovrete cambiarla all'interno della apposita variabile e assicurarvi che il valore venga assegnato all'inizio. A tal proposito, sarebbe una buona idea assegnare il valore successviamente al codice di identificazione della macchina (quello visto all'inzio di questa guida).
Riavvio e Spegnimento
Il chipset dell'Xbox non ha alcuna funzionalità ACPI, così non è possibile spegnere la macchina utilizzando il protocollo ACPI. Non è nemmeno possibile riavviare l'Xbox come se fosse un PC poichè priva di controller della tastiera che solitamente include questa funzione. Entrambe queste funzioni vengono gestite dal "System Management Controller" SMC (anche detto "PIC"), che è un device situato sul SMBus.
Per comunicare con un device del SMBus avete bisogno di un driver per il controller del SMBus dell'Xbox, che è AMD754-compatibile. Linux per esempio include questo driver, ma non c'è realmente bisogno di includere un driver completo per il bus solo per questa semplice funzione. Il SMBus sull'Xbox è semplice a sufficienza da poter essere controllato con due piccole funzioni di C. Il codice seguente è tutto ciò di cui avete bisogno:
#define XBOX_SMB_IO_BASE 0xC000
#define XBOX_SMB_GLOBAL_ENABLE (0x2 + XBOX_SMB_IO_BASE)
#define XBOX_SMB_HOST_ADDRESS (0x4 + XBOX_SMB_IO_BASE)
#define XBOX_SMB_HOST_DATA (0x6 + XBOX_SMB_IO_BASE)
#define XBOX_SMB_HOST_COMMAND (0x8 + XBOX_SMB_IO_BASE)
#define XBOX_PIC_ADDRESS 0x10
#define SMC_CMD_POWER 0x02
#define SMC_SUBCMD_POWER_RESET 0x01
#define SMC_SUBCMD_POWER_CYCLE 0x40
#define SMC_SUBCMD_POWER_OFF 0x80
static void xbox_pic_cmd(u8 command)
{
outw_p(((XBOX_PIC_ADDRESS) << 1), XBOX_SMB_HOST_ADDRESS);
outb_p(SMC_CMD_POWER, XBOX_SMB_HOST_COMMAND);
outw_p(command, XBOX_SMB_HOST_DATA);
outw_p(inw(XBOX_SMB_IO_BASE), XBOX_SMB_IO_BASE);
outb_p(0x0a, XBOX_SMB_GLOBAL_ENABLE);
}
void xbox_power_reset(char * __unused)
{
xbox_pic_cmd(SMC_SUBCMD_POWER_RESET);
}
void xbox_power_cycle(char * __unused)
{
xbox_pic_cmd(SMC_SUBCMD_POWER_CYCLE);
}
void xbox_power_off(void)
{
xbox_pic_cmd(SMC_SUBCMD_POWER_OFF);
}
xbox_power_reset semplicemente resetta il sistema mentre xbox_power_cycle spegne la macchina e la riaccende dopo mezzo secondo.
Notate che il codice qui sopra è privo di stutture per il controllo degli errori e non andrebbe utilizzato in generale.
DVD Driver
Nonostante i drives DVD dell'Xbox siano essenzialmente dei drives IDE standard, esistono alcune differenze, alcune dovute a problemi di protezione e alcune altre dovute a bugs dei rispettivi firmwares.
Riavvio all' Eject
Sulla Playstation era possibile aggirare il sistema di protezione della console facendo bootare delle copie originali per poi inserire velocemente copie di backup. Gli ideatori dell'Xbox hanno di fatto reso inattuabile questo trick grazie ad un chip di sicurezza addizionale, il chip SMC, che resetta il sistema se l'utente preme il tasto di eject or se prova ad aprire manualmente il carrellino del drive DVD. Il sistema tuttavia non viene sempre riavviato in questo caso. Dalla dashboard Xbox è possibile, per esempio, far aprire lo sportello. Ogni volta che l'utente preme il tasto di eject o lo sportellino si apre ( per esempio se lo sportello del drive DVD si apre su richiesta del software ), il PIC invia un interrupt EXTSMI# alla CPU. Se il software eseguito dalla CPU gestisce questo interrupt e restituisce al PIC un messaggio, allora il sistema non viene resettato.
Il codice in [1] (http://cvs.sourceforge.net/viewcvs.py/xbox-linux/kernel-2.6/arch/i386/mach-xbox/reset-on-eject.c?rev=1.2&view=autoarch/i386/mach-xbox/reset-on-eject.c) nel kernel di Xbox Linux gestisce tutto ciò. Nuovamente avete bisogno del codice del SMBus per dialogare con SMC.
DVD Drive Bugs
Microsoft utilizza drives DVD differenti sull'Xbo, alcuni dei quali hanno problemi di compatibilità:
| stringa drive | problema |
| "THOMSON-DVD" | finge di non poter riprodurre audio o dvd; non comprende il comando di
eject ATAPI |
| "PHILIPS XBOX DVD DRIVE" | non comprende il comando di eject ATAPI |
| "PHILIPS J5 3235C" | finge di non poter riprodurre audio o dvd |
| "SAMSUNG DVD-ROM SDG-605B" | nessun problema |
In aggiunta nessuno di questi drives rispetta il blocco della porta quando l'utente preme il tasto di eject.
Se lasciate le cose così come sono, alcuni drives non risponderanno ai comandi software di eject e altri rifiuteranno di riprodurre DVD o contenuti audio e il riproduttore software penserà che il drive non è realmente in grado di farlo. Per poter supportare completamente tutti questi drives DVD, dovete aggiungere alcune righe di codice al codice del driver ATAPI CD/DVD nel vostro sistema operativo, che probabilmente già include alcuni test per altri devices. la tabella sottostante include le stringhe esatte per identificare i vari lettori Xbox.
Se il drive non comprende il comando ATAPI di eject (così come il comando di load), dovrete passare al SMC un comando di eject. Il file [2] (http://cvs.sourceforge.net/viewcvs.py/xbox-linux/kernel-2.6/include/linux/xbox.h?rev=1.1&view=autoinclude/linux/xbox.h) include il codice di cui avete bisogno. Le due linee seguenti sono prese da questo file:
#define Xbox_tray_load() Xbox_SMC_write(SMC_CMD_EJECT, SMC_SUBCMD_EJECT_LOAD); #define Xbox_tray_eject() Xbox_SMC_write(SMC_CMD_EJECT, SMC_SUBCMD_EJECT_EJECT);
Vi prego di notare che avere un lettore DVD Xbox installato non significa necessariamente che stiate lavorando su una Xbox. E' possibile (sebbene impraticabile per via dell'incompatibilità tra i connettori dell'alimentazione) utilizzare i lettori Xbox su un PC standard. Quindi se il drive non comprende il comando ATAPI di eject e non ci troviamo su una Xbox non c'è verso di far sì che il carrellino venga espulso dato che il drive non possiede un proprio tasto di eject e che non potete ovviamente inviare dei comandi SMC sul PC.
L'implementazione di Linux per questo comportamento si trova qui [3] (http://cvs.sourceforge.net/viewcvs.py/xbox-linux/kernel-2.6/drivers/ide/ide-cd.c?rev=1.13&view=autodrivers/ide/ide-cd.c) Una volta identificati i drives, il driver annota nella struttura del kernel del drive se si tratta di un drive Xbox, se supporta l'eject e corregge gli errori di funzionalità.
Dal momento che il pulsante di eject, collegato al SMC, non rispetta lo stato di locking dello sportellino, il driver simula ciò via software.
Locking/unlocking the door:
if (xbox_drive && machine_is_xbox) {
simulated_lock = lock;
}
Ejecting/loading:
if (machine_is_xbox && xbox_drive && cannot_eject) {
if (load) {
Xbox_tray_load();
} else {
simulated_lock = 0;
Xbox_tray_eject();
}
return;
}
Il driver per il riavvio all'eject, che cattura la pressione del bottone di eject, dovrebbe così respettare anche la flag "simulated_lock" e non aprire lo sportello se è stato bloccato via software.
Vi prego di notare anche chesebbene alcune flag delle funzioni del drive Xbox siano corrette, il software potrebbe avere problemi con queste. Un esempio su Unix è cdparanoia: se un lettore CD ha un uscite per le cuffie, allora l'OS presume che debba supportare la riproduzione di CD audio. Questo è logico. Tuttavia cdparanoia presume che se un drive è sprovvisto del jack per le cuffie, questo non sia in grado di riprodurre Cd audio, e ovviamente questo non è vero. Tutti i lettori DVD Xbox possono rippare CD audio ma nessuno di loro è dotato di un uscita audio per cuffie.
Driver Video
Supporta pienamente l'hardware video dell'Xbox potrebbe implicare parecchio lavoro ( o quanto meno la copia di gran parte del kernel Xbox). In realtà non è necessario implementare un driver video completo. Entrambi i bootloaders dell'Xbox Linux project impostano lo schermo a 640x480 (colore a 32 bit, RGBX), che nella maggior parte delle configurazioni è sufficiente. Questo framebuffer lineare si trova in cima alla memoria (circa 60 mb) e può essere utilizzato dal vostro sistema operativo senza dover toccare i registri video. Semplicemente funziona come le modalità VESA supportate da molti sistemi operativi, che vengono settate dal boot loader ( utilizzando le funzioni del BIOS) e non vengono più switchate. date uno sguardo alla sezione bootloader to apprendere dove questao framebuffer è allocato.
Se volete pieno supporto, potete utilizzare il codice del driver per l'hardware nVidia dato che l'hardware video Xbox è pienamente nVidia-compatibile. L'unico problema sta nel fatto che l'XBox non ha una VGA RAMDAC ma un encoder video PAL/NTSC ( che è connesso tramite SMBus) , avete quindi sempre bisogno di accertarvi che ogni qual volta impostiate una nuova modalità , anche l'encoder video sia settato correttamente, in caso contrario noterete la solita videata-spazzatura a schermo.
Sfortunatamente, uno dei tre encoder video che equipaggiano le diverse versioni di Xbox p incompatibile: le prime Xboxes utilizzavano i chips Connexant (1.0-1.3), le successive utilizzavano componenti Focus (1.4-1.5), infine le Xboxes 1.6 includono una unità integrata targata Xcalibur. Ecco spiegato il motivo per cui potreste dover copiare diverse parti di codice dal kernel di Xbox Linux e dovreste poter disporre di diverse versioni di Xbox per testare il vostro codice. Potete trovare qui il codice relativo a quanto appena spiegato drivers/video/xbox/* (http://cvs.sourceforge.net/viewcvs.py/xbox-linux/kernel-2.6/drivers/video/xbox/).
Hard Disk
L'Xbox include un hard disk standard di 8 o 10 GB. Per ragioni di sicurezza (l'utente non dovrebbe essere in grado di connetterli a un PC) questi HDs sono bloccati con una password ATA, ma dato che il firmware li sblocca non dovreste preoccuparvi a meno che non inviate dei comandi ATA di reset al drive (cosa da evitare).
Tuttavia potreste voler far coesistere il vostro sistema operativo con il software di sistema dell'Xbox. In tal caso dovrete rispettare il partizionamento pre-esistente e installare l'OS ( probabilmente come file immagine) su una partizione esistente.
Partizionamento Xbox
L'Xbox usa uno schema implicito di partizionamento, descritto negli articoli Xbox Partitioning and Filesystem Details e Xbox Hard Disk Partitioning. Al fine di stabilire se l'hard disk è partizionato secondo il modello Xbox, dovrete controllare il magico valore del "BRFR", che dovrebbe essere sempre presente. Potete anche controllare l'intestazione "FATX" nel "System Files" della partizione (C:), senza considerare altre intestazioni FATX.
Dovreste inoltre creare una sesta partizione con una capacità compresa tra 8 GB e 137 GB e una settima partizione per lo psazio superiore ai 137 GB in modo da essere compatibile con i kernels Xbox patchati che lavorano con hard disk di grossa capacità. Potreste voler considerare di permettere due partizionamenti si sistema attivi allo stesso tempo: il partizionamento Xbox, che definisce (almeno) i primi 8 GB e il partizionamento in stile PC utilizzando delle tabelle di partizione per PC (il primo settore dell'HD non viene utilizzato). Di conseguenza, in Xbox Linux, alle partizioni Xbox vengono assegnate i numeri 50 e 56 mentre le partizioni PC cominciando da 1.
In Xbox Linux, questo codice risiede in [4] (http://cvs.sourceforge.net/viewcvs.py/xbox-linux/kernel-2.6/fs/partitions/check.c?rev=1.9&view=autofs/partitions/check.c) e [5] (http://cvs.sourceforge.net/viewcvs.py/xbox-linux/kernel-2.6/fs/partitions/xbox.c?rev=1.7&view=autofs/partitions/xbox.c).
FATX Filesystem
Sull'HD, l'xbox utilizza esclusivamente il filesystem FATX, una versione semplificata del filesystem FAT16/FAT32. Gli articoli Xbox Partitioning and Filesystem Details e Differences between Xbox FATX and MS-DOS FAT illustrano nel dettaglio il filesystem FATX.
Periferiche
Gamepad Xbox
Il gamepad Xbox è un device USB dotato di protocollo proprietario che potete trovare nel kernel di Xbox Linux: [6] (http://cvs.sourceforge.net/viewcvs.py/xbox-linux/kernel-2.6/drivers/usb/input/xpad.c?rev=1.5&view=autodrivers/usb/input/xpad.c). Potreste comunque voler aggiungere l'emulazione per il mouse e/o la tastiera.
Telecomando
Il telecomando è simile al gamepad. potrebbe anch'esso emulare mouse e tastiera.
<! --==== Cuffie Xbox Live ==== -->
Altri Componenti di Sistema
USB
L'Xbox ha un host controller OHCI standard che il vostro sistema operativo dovrebbe fortunatamente supportare.
Ethernet
Il controller ethernet dell'Xbox è un nForce "nvnet". Il driver Linux forcedeth (http://www.hailfinger.org/carldani/linux/patches/forcedeth/) lo supporta completamente.
Sensori
Sull'Xbox sono presenti due sensori per la misurazione della temperatura ( CPU e sistema). I dirvers standard di Linux sopportano entrambi i sensori. Siete in grado di controllare il sistema di ventole attraverso SMC. Date un occhio al codice sorgente dei "tools" di Xbox Linux per i dettagli.
Dove inserire il codice per SMBus
Diverse parti del sistema operativo (eject, riavvo all'eject, e riavvio) devono poter dialogare con SMC che si trova su SMBus. Anche l'encoder video è situato su SMBus. Di conseguenza la questione è se volete includere una libreria centrale per SMBus nel kernel oppure se volete duplicare il codice.
Xbox Linux ha duplicato il codice diverse volte: il codice che dialoga con SMC include le stesse funzioni di SMBus e il driver video, che ha anche accesso all'encoder video

