summaryrefslogtreecommitdiff
path: root/src/bios.h
blob: b420fff6d1db45ce67adc9dd9f9fc05f51300c4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
/*
 * <bios.h>
 *
 * header for Open Hack'Ware
 * 
 * Copyright (c) 2004-2005 Jocelyn Mayer
 * 
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License V2
 *   as published by the Free Software Foundation
 *
 *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#if !defined (__BIOS_H__)
#define __BIOS_H__

#define USE_OPENFIRMWARE
//#define DEBUG_BIOS 1

#define BIOS_VERSION "0.4.1"

#define DSISR 18
#define DAR   19
#define SRR0  26
#define SRR1  27

#define _tostring(s) #s
#define stringify(s) _tostring(s)

#if !defined (ASSEMBLY_CODE)

#ifdef DEBUG_BIOS
#define DPRINTF(fmt, args...) do { dprintf(fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do { } while (0)
#endif
#define ERROR(fmt, args...) do { printf("ERROR: " fmt , ##args); } while (0)
#define MSG(fmt, args...) do { printf(fmt , ##args); } while (0)

#define offsetof(_struct, field)                                      \
({                                                                    \
    typeof(_struct) __tmp_struct;                                     \
    int __off;                                                        \
    __off = (char *)(&__tmp_struct.field) - (char *)(&__tmp_struct);  \
    __off;                                                            \
})

#define unused __attribute__ (( unused)) 

/* Useful macro in C code */
#define MTSPR(num, value)                                            \
__asm__ __volatile__ ("mtspr " stringify(num) ", %0" :: "r"(value));

/* Architectures */
enum {
    ARCH_PREP = 0,
    ARCH_CHRP,
    ARCH_MAC99,
    ARCH_POP,
};

/* Hardware definition(s) */
extern uint32_t isa_io_base;
#define ISA_IO_BASE 0x80000000
extern int arch;

/*****************************************************************************/
/* From start.S : BIOS start code and asm helpers */
void transfer_handler (void *residual, void *load_addr,
                       void *OF_entry, void *bootinfos,
                       void *cmdline, void *not_used,
                       void *nip, void *stack_base);
void bug (void);

/* PPC helpers */
uint32_t mfmsr (void);
void mtmsr (uint32_t msr);
uint32_t mfpvr (void);
void mftb (uint32_t *tb);
void MMU_on (void);
void MMU_off (void);
/* IO helpers */
uint32_t inb (uint16_t port);
void outb (uint16_t port, uint32_t val);
uint32_t inw (uint16_t port);
void outw (uint16_t port, uint32_t val);
uint32_t inl (uint16_t port);
void outl (uint16_t port, uint32_t val);
void eieio (void);
/* Misc helpers */
uint16_t ldswap16 (uint16_t *addr);
void stswap16 (void *addr, uint16_t val);
uint32_t ldswap32 (uint32_t *addr);
void stswap32 (void *addr, uint32_t val);
void mul64 (uint32_t *ret, uint32_t a, uint32_t b);
void add64 (uint32_t *ret, uint32_t *a, uint32_t *b);

typedef struct jmp_buf {
    uint32_t gpr[32];
    uint32_t lr;
    uint32_t ctr;
    uint32_t xer;
    uint32_t ccr;
} jmp_buf;
int setjmp (jmp_buf env);
void longjmp (jmp_buf env);

/*****************************************************************************/
/* PCI BIOS                                                                  */
typedef struct pci_common_t pci_common_t;
typedef struct pci_host_t pci_host_t;
typedef struct pci_device_t pci_device_t;
typedef struct pci_bridge_t pci_bridge_t;
typedef struct pci_ops_t pci_ops_t;
typedef union pci_u_t pci_u_t;

typedef struct pci_dev_t pci_dev_t;
struct pci_dev_t {
    uint16_t vendor;
    uint16_t product;
    const unsigned char *type;
    const unsigned char *name;
    const unsigned char *model;
    const unsigned char *compat;
    int acells;
    int scells;
    int icells;
    int (*config_cb)(pci_device_t *device);
    const void *private;
};

pci_host_t *pci_init (void);
void pci_get_mem_range (pci_host_t *host, uint32_t *start, uint32_t *len);

/*****************************************************************************/
/* nvram.c : NVRAM management routines */
typedef struct nvram_t nvram_t;
extern nvram_t *nvram;

uint8_t NVRAM_read (nvram_t *nvram, uint32_t addr);
void NVRAM_write (nvram_t *nvram, uint32_t addr, uint8_t value);
uint16_t NVRAM_get_size (nvram_t *nvram);
int NVRAM_format (nvram_t *nvram);
nvram_t *NVRAM_get_config (uint32_t *RAM_size, int *boot_device,
                           void **boot_image, uint32_t *boot_size,
                           void **cmdline, uint32_t *cmdline_size,
                           void **ramdisk, uint32_t *ramdisk_size);

/*****************************************************************************/
/* bloc.c : bloc devices management */
typedef struct pos_t {
    uint32_t bloc;
    uint32_t offset;
} pos_t;

typedef struct bloc_device_t bloc_device_t;
typedef struct part_t part_t;
typedef struct fs_t fs_t;

bloc_device_t *bd_open (int device);
int bd_seek (bloc_device_t *bd, uint32_t bloc, uint32_t pos);
int bd_read (bloc_device_t *bd, void *buffer, int len);
int bd_write (bloc_device_t *bd, const void *buffer, int len);
#define _IOCTL(a, b) (((a) << 16) | (b))
#define MEM_SET_ADDR _IOCTL('M', 0x00)
#define MEM_SET_SIZE _IOCTL('M', 0x01)
int bd_ioctl (bloc_device_t *bd, int func, void *args);
uint32_t bd_seclen (bloc_device_t *bd);
void bd_close (bloc_device_t *bd);
uint32_t bd_seclen (bloc_device_t *bd);
uint32_t bd_maxbloc (bloc_device_t *bd);
void bd_sect2CHS (bloc_device_t *bd, uint32_t secnum,
                  int *cyl, int *head, int *sect);
uint32_t bd_CHS2sect (bloc_device_t *bd,
                      int cyl, int head, int sect);
part_t *bd_probe (int boot_device);
bloc_device_t *bd_get (int device);
void bd_put (bloc_device_t *bd);
void bd_set_boot_part (bloc_device_t *bd, part_t *partition);
part_t **_bd_parts (bloc_device_t *bd);

void ide_pci_pc_register (uint32_t io_base0, uint32_t io_base1,
                          uint32_t io_base2, uint32_t io_base3,
                          void *OF_private);
void ide_pci_pmac_register (uint32_t io_base0, uint32_t io_base1,
                            void *OF_private);

/*****************************************************************************/
/* part.c : partitions management */
enum part_flags_t {
    PART_TYPE_RAW     = 0x0000,
    PART_TYPE_PREP    = 0x0001,
    PART_TYPE_APPLE   = 0x0002,
    PART_TYPE_ISO9660 = 0x0004,
    PART_FLAG_DUMMY   = 0x0010,
    PART_FLAG_DRIVER  = 0x0020,
    PART_FLAG_PATCH   = 0x0040,
    PART_FLAG_FS      = 0x0080,
    PART_FLAG_BOOT    = 0x0100,
};

enum {
    PART_PREP = 0x01,
    PART_CHRP = 0x02,
};

part_t *part_open (bloc_device_t *bd,
                   uint32_t start, uint32_t size, uint32_t spb);
int part_seek (part_t *part, uint32_t bloc, uint32_t pos);
int part_read (part_t *part, void *buffer, int len);
int part_write (part_t *part, const void *buffer, int len);
void part_close (part_t *part);
uint32_t part_blocsize (part_t *part);
uint32_t part_flags (part_t *part);
uint32_t part_size (part_t *part);
fs_t *part_fs (part_t *part);

part_t *part_get (bloc_device_t *bd, int partnum);
part_t *part_probe (bloc_device_t *bd, int set_raw);
int part_set_boot_file (part_t *part, uint32_t start, uint32_t offset,
                        uint32_t size);

/*****************************************************************************/
/* fs.c : file system management */
typedef struct dir_t dir_t;
typedef struct dirent_t dirent_t;
typedef struct inode_t inode_t;

struct dirent_t {
    dir_t *dir;
    inode_t *inode;
    const unsigned char *dname;
};

enum {
    INODE_TYPE_UNKNOWN = 0x00FF,
    INODE_TYPE_DIR     = 0x0000,
    INODE_TYPE_FILE    = 0x0001,
    INODE_TYPE_OTHER   = 0x0002,
    INODE_TYPE_MASK    = 0x00FF,
    INODE_FLAG_EXEC    = 0x0100,
    INODE_FLAG_BOOT    = 0x0200,
    INODE_FLAG_MASK    = 0xFF00,
};

/* probe a filesystem from a partition */
fs_t *fs_probe (part_t *part, int set_raw);
part_t *fs_part (fs_t *fs);
/* Recurse thru directories */
dir_t *fs_opendir (fs_t *fs, const unsigned char *name);
dirent_t *fs_readdir (dir_t *dir);
unsigned char *fs_get_path (dirent_t *dirent);
void fs_closedir (dir_t *dir);
/* Play with files */
inode_t *fs_open (fs_t *fs, const unsigned char *name);
int fs_seek (inode_t *inode, uint32_t bloc, uint32_t pos);
int fs_read (inode_t *inode, void *buffer, int len);
int fs_write (inode_t *inode, const void *buffer, unused int len);
void fs_close (inode_t *inode);
uint32_t fs_get_type (fs_t *fs);
uint32_t fs_inode_get_type (inode_t *inode);
uint32_t fs_inode_get_flags (inode_t *inode);
part_t *fs_inode_get_part (inode_t *inode);

/* Bootfile */
unsigned char *fs_get_boot_dirname (fs_t *fs);
inode_t *fs_get_bootfile (fs_t *fs);
int fs_raw_set_bootfile (part_t *part,
                         uint32_t start_bloc, uint32_t start_offset,
                         uint32_t size_bloc, uint32_t size_offset);

/*****************************************************************************/
/* file.c : file management */
#define DEFAULT_LOAD_DEST 0x00100000

uint32_t file_seek (inode_t *file, uint32_t pos);

/* Executable files loader */
int bootfile_load (void **dest, void **entry, void **end,
                   part_t *part, int type, const unsigned char *fname,
                   uint32_t offset);

/*****************************************************************************/
/* char.c : char devices */
typedef struct chardev_t chardev_t;
typedef struct cops_t cops_t;

struct cops_t {
    int (*open)(void *private);
    int (*close)(void *private);
    int (*read)(void *private);
    int (*write)(void *private, int c);
    /* Won't implement seek for now */
};

enum {
    CHARDEV_KBD = 0,
    CHARDEV_MOUSE,
    CHARDEV_SERIAL,
    CHARDEV_DISPLAY,
    CHARDEV_LAST,
};

int chardev_register (int type, cops_t *ops, void *private);
int chardev_open (chardev_t *dev);
int chardev_close (chardev_t *dev);
int chardev_read (chardev_t *dev, void *buffer, int maxlen);
int chardev_write (chardev_t *dev, const void *buffer, int maxlen);
int chardev_type (chardev_t *dev);

/* Console driver */
int console_open (void);
int console_read (void *buffer, int maxlen);
int console_write (const void *buffer, int len);
void console_close (void);

/* PC serial port */
#define SERIAL_OUT_PORT (0x03F8)
int pc_serial_register (uint16_t base);

/* CUDA host */
typedef struct cuda_t cuda_t;
cuda_t *cuda_init (uint32_t base);
void cuda_reset (cuda_t *cuda);

/*****************************************************************************/
/* vga.c : VGA console */
extern unsigned long vga_fb_phys_addr;
extern int vga_fb_width;
extern int vga_fb_height;
extern int vga_fb_linesize;
extern int vga_fb_bpp;
extern int vga_fb_depth;
void vga_prep_init(void);
void vga_set_address (uint32_t address);
void vga_set_mode(int width, int height, int depth);
void vga_set_palette(int i, unsigned int rgba);
#define RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define RGB(r, g, b) RGBA(r, g, b, 0xff)
unsigned int vga_get_color(unsigned int rgba);

void vga_draw_buf (const void *buf, int buf_linesize,
                   int posx, int posy, int width, int height);
void vga_fill_rect (int posx, int posy, int width, int height, uint32_t color);
void vga_bitblt(int xs, int ys, int xd, int yd, int w, int h);
void vga_check_mode(int width, int height, int depth);

/* text primitives */
void vga_text_set_fgcol(unsigned int rgba);
void vga_text_set_bgcol(unsigned int rgba);
void vga_putcharxy(int x, int y, int ch,
                   unsigned int fgcol, unsigned int bgcol);
void vga_putchar(int ch);
void vga_puts(const char *s);

/*****************************************************************************/
/* bootinfos.c : build structures needed by kernels to boot */
void prepare_bootinfos (void *p, uint32_t memsize,
                        void *cmdline, void *initrd, uint32_t initrd_size);
void residual_build (void *p, uint32_t memsize,
                     uint32_t load_base, uint32_t load_size,
                     uint32_t last_alloc);

/*****************************************************************************/
/* of.c : Open-firmware emulation */
#define OF_NAMELEN_MAX 1024
#define OF_PROPLEN_MAX 256

int OF_init (void);
int OF_register_mb (const unsigned char *model, const unsigned char **compats);
int OF_register_cpu (const unsigned char *name, int num, uint32_t pvr,
                     uint32_t min_freq, uint32_t max_freq, uint32_t bus_freq,
                     uint32_t tb_freq, uint32_t reset_io);
#if 0
int OF_register_translations (int nb, OF_transl_t *translations);
#endif
uint32_t OF_claim_virt (uint32_t virt, uint32_t size, int *range);
int OF_register_memory (uint32_t memsize, uint32_t bios_size);
int OF_register_bootargs (const unsigned char *bootargs);
void *OF_register_pci_host (pci_dev_t *dev, uint16_t rev, uint32_t ccode,
                            uint32_t cfg_base, uint32_t cfg_len,
                            uint32_t mem_base, uint32_t mem_len,
                            uint32_t io_base, uint32_t io_len,
                            uint32_t rbase, uint32_t rlen,
                            uint16_t min_grant, uint16_t max_latency);
void *OF_register_pci_bridge (void *parent, pci_dev_t *dev,
                              uint32_t cfg_base, uint32_t cfg_len,
                              uint8_t devfn, uint8_t rev, uint32_t ccode,
                              uint16_t min_grant, uint16_t max_latency);
void *OF_register_pci_device (void *parent, pci_dev_t *dev,
                              uint8_t devfn, uint8_t rev, uint32_t ccode,
                              uint16_t min_grant, uint16_t max_latency);
void OF_finalize_pci_host (void *dev, int first_bus, int nb_busses);
void OF_finalize_pci_device (void *dev, uint8_t bus, uint8_t devfn,
                             uint32_t *regions, uint32_t *sizes);
void OF_finalize_pci_macio (void *dev, uint32_t base_address, uint32_t size,
                            void *private_data);
int OF_register_bus (const unsigned char *name, uint32_t address,
                     const unsigned char *type);
int OF_register_serial (const unsigned char *bus, const unsigned char *name,
                        uint32_t io_base, int irq);
int OF_register_stdio (const unsigned char *dev_in,
                       const unsigned char *dev_out);
void OF_vga_register (const unsigned char *name, uint32_t address,
                      int width, int height, int depth);
void *OF_blockdev_register (void *parent, void *private,
                            const unsigned char *type,
                            const unsigned char *name, int devnum,
                            const char *alias);
void OF_blockdev_set_boot_device (void *disk, int partnum,
                                  const unsigned char *file);

int OF_entry (void *p);
int OF_client_entry (void *p);
void RTAS_init (void);

/*****************************************************************************/
/* main.c : main BIOS code */
/* Memory management */
/* Memory areas */
extern uint32_t _data_start, _data_end;
extern uint32_t _OF_vars_start, _OF_vars_end;
extern uint32_t _sdata_start, _sdata_end;
extern uint32_t _ro_start, _ro_end;
extern uint32_t _RTAS_start, _RTAS_end;
extern uint32_t _RTAS_data_start, _RTAS_data_end;
extern uint32_t _bss_start, _bss_end;
extern uint32_t _ram_start;
extern const unsigned char *BIOS_str;
extern const unsigned char *copyright;
void *mem_align (int align);
void freep (void *p);

/* Endian-safe memory read/write */
static inline void put_be64 (void *addr, uint64_t l)
{
    *(uint64_t *)addr = l;
}

static inline uint64_t get_be64 (void *addr)
{
    return *(uint64_t *)addr;
}

static inline void put_le64 (void *addr, uint64_t l)
{
    uint32_t *p;

    p = addr;
    stswap32(p, l);
    stswap32(p + 1, l >> 32);
}

static inline uint64_t get_le64 (void *addr)
{
    uint64_t val;
    uint32_t *p;

    p = addr;
    val = ldswap32(p);
    val |= (uint64_t)ldswap32(p + 1) << 32;
    
    return val;
}

static inline void put_be32 (void *addr, uint32_t l)
{
    *(uint32_t *)addr = l;
}

static inline uint32_t get_be32 (void *addr)
{
    return *(uint32_t *)addr;
}

static inline void put_le32 (void *addr, uint32_t l)
{
    stswap32(addr, l);
}

static inline uint32_t get_le32 (void *addr)
{
    return ldswap32(addr);
}

static inline void put_be16 (void *addr, uint16_t l)
{
    *(uint16_t *)addr = l;
}

static inline uint16_t get_be16 (void *addr)
{
    return *(uint16_t *)addr;
}

static inline void put_le16 (void *addr, uint16_t l)
{
    stswap16(addr, l);
}

static inline uint16_t get_le16 (void *addr)
{
    return ldswap16(addr);
}

/* String functions */
long strtol (const unsigned char *str, unsigned char **end, int base);

int write_buf (const unsigned char *buf, int len);

/* Misc */
void usleep (uint32_t usec);
void sleep (int sec);
uint32_t crc32 (uint32_t crc, const uint8_t *p, int len);
void set_loadinfo (void *load_base, uint32_t size);
void set_check (int do_it);
void check_location (const void *buf, const char *func, const char *name);

static inline void pokeb (void *location, uint8_t val)
{
#ifdef DEBUG_BIOS
    check_location(location, __func__, "location");
#endif
    *((uint8_t *)location) = val;
}

static inline uint8_t peekb (void *location)
{
#ifdef DEBUG_BIOS
    check_location(location, __func__, "location");
#endif
    return *((uint8_t *)location);
}

static inline void pokew (void *location, uint16_t val)
{
#ifdef DEBUG_BIOS
    check_location(location, __func__, "location");
#endif
    *((uint8_t *)location) = val;
}

static inline uint16_t peekw (void *location)
{
#ifdef DEBUG_BIOS
    check_location(location, __func__, "location");
#endif
    return *((uint16_t *)location);
}

static inline void pokel (void *location, uint32_t val)
{
#ifdef DEBUG_BIOS
    check_location(location, __func__, "location");
#endif
    *((uint32_t *)location) = val;
}

static inline uint32_t peekl (void *location)
{
#ifdef DEBUG_BIOS
    check_location(location, __func__, "location");
#endif
    return *((uint32_t *)location);
}

/* Console */
int cs_write (const unsigned char *buf, int len);

#endif /* !defined (ASSEMBLY_CODE) */


#endif /* !defined (__BIOS_H__) */