This repository has been archived by the owner on Dec 12, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
bender.c
111 lines (88 loc) · 2.8 KB
/
bender.c
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
/* -*- Mode: C -*- */
#include <pci.h>
#include <mbi.h>
#include <util.h>
#include <elf.h>
#include <version.h>
#include <serial.h>
#include <bda.h>
/* Configuration (set by command line parser) */
static bool be_promisc = false;
static uint64_t phys_max_relocate = 1ULL << 31; /* below 2G */
void
parse_cmdline(const char *cmdline)
{
char *last_ptr = NULL;
char cmdline_buf[256];
char *token;
unsigned i;
strncpy(cmdline_buf, cmdline, sizeof(cmdline_buf));
for (token = strtok_r(cmdline_buf, " ", &last_ptr), i = 0;
token != NULL;
token = strtok_r(NULL, " ", &last_ptr), i++) {
/* Our name is not interesting. */
if (i == 0)
continue;
if (strcmp(token, "promisc") == 0) {
be_promisc = true;
}
if (strcmp(token, "phys_max=256M") == 0)
phys_max_relocate = 256ULL * 1024 * 1024;
}
}
static uint16_t apply_quirks(struct pci_device *pcid, uint16_t raw_iobase)
{
uint32_t vendormodel = pci_cfg_read_uint32(pcid, 0);
if (vendormodel == 0x32531c00) {
printf("Found XR16850 chip. Adding 0xc0 to iobase offset.\n");
return raw_iobase + 0xc0;
}
return raw_iobase;
}
int
main(uint32_t magic, struct mbi *mbi)
{
if (magic == MBI_MAGIC) {
if ((mbi->flags & MBI_FLAG_CMDLINE) != 0)
parse_cmdline((const char *)mbi->cmdline);
} else {
printf("Not loaded by Multiboot-compliant loader. Bye.\n");
return 1;
}
printf("\nBender %s\n", version_str);
printf("Blame Julian Stecklina <jsteckli@os.inf.tu-dresden.de> for bugs.\n\n");
printf("Looking for serial controllers on the PCI bus...\n");
struct pci_device serial_ctrl;
printf("Promisc is %s.\n", be_promisc ? "on" : "off");
if (pci_find_device_by_class(PCI_CLASS_SIMPLE_COMM,
be_promisc ? PCI_SUBCLASS_ANY : PCI_SUBCLASS_SERIAL_CTRL,
&serial_ctrl)) {
printf(" found at %x.\n", serial_ctrl.cfg_address);
} else {
printf(" none found.\n");
goto boot_next;
}
uint16_t iobase = 0;
for (unsigned bar_no = 0; bar_no < 6; bar_no++) {
uint32_t bar = pci_cfg_read_uint32(&serial_ctrl, PCI_CFG_BAR0 + 4*bar_no);
if ((bar & PCI_BAR_TYPE_MASK) == PCI_BAR_TYPE_IO) {
iobase = bar & PCI_BAR_IO_MASK;
break;
}
}
iobase = apply_quirks(&serial_ctrl, iobase);
uint16_t *com0_port = (uint16_t *)(get_bios_data_area());
uint16_t *equipment_word = &get_bios_data_area()->equipment;
if (iobase != 0) {
printf("Patching BDA with I/O port 0x%x.\n", iobase);
*com0_port = iobase;
*equipment_word = (*equipment_word & ~(0xF << 9)) | (1 << 9); /* One COM port available */
} else {
printf("I/O ports for controller not found.\n");
}
boot_next:
if (serial_ports(get_bios_data_area()))
serial_init();
printf("Bender: Hello World.\n");
return start_module(mbi, false, phys_max_relocate);
}