static void pci_bus_assign_space(pci_bus_t *pcibus, intptr_t mem_base, intptr_t io_base) { pci_bar_t **bars = kernel_sbrk(0); unsigned nbars = 0; for (int j = 0; j < pcibus->ndevs; j++) { pci_device_t *pcidev = &pcibus->dev[j]; for (int i = 0; i < pcidev->nbars; i++) { void *ptr __attribute__((unused)); ptr = kernel_sbrk(sizeof(pci_bar_t *)); bars[nbars++] = &pcidev->bar[i]; } } qsort(bars, nbars, sizeof(pci_bar_t *), pci_bar_compare); for (int j = 0; j < nbars; j++) { pci_bar_t *bar = bars[j]; if (bar->addr & PCI_BAR_IO) { bar->addr |= io_base; io_base += bar->size; } else { bar->addr |= mem_base; mem_base += bar->size; } } kernel_brk(bars); }
static void pci_bus_enumerate(pci_bus_t *pcibus) { pcibus->dev = kernel_sbrk(0); pcibus->ndevs = 0; for (int j = 0; j < 32; j++) { for (int k = 0; k < 8; k++) { PCI0_CFG_ADDR_R = PCI0_CFG_ENABLE | PCI0_CFG_REG(j, k, 0); if (PCI0_CFG_DATA_R == -1) continue; pci_device_t *pcidev = kernel_sbrk(sizeof(pci_device_t)); pcidev->addr.bus = 0; pcidev->addr.device = j; pcidev->addr.function = k; pcidev->device_id = PCI0_CFG_DATA_R >> 16; pcidev->vendor_id = PCI0_CFG_DATA_R; PCI0_CFG_ADDR_R = PCI0_CFG_ENABLE | PCI0_CFG_REG(j, k, 2); pcidev->class_code = (PCI0_CFG_DATA_R & 0xff000000) >> 24; PCI0_CFG_ADDR_R = PCI0_CFG_ENABLE | PCI0_CFG_REG(j, k, 15); pcidev->pin = PCI0_CFG_DATA_R >> 8; pcidev->irq = PCI0_CFG_DATA_R; for (int i = 0; i < 6; i++) { PCI0_CFG_ADDR_R = PCI0_CFG_ENABLE | PCI0_CFG_REG(pcidev->addr.device, pcidev->addr.function, 4 + i); unsigned addr = PCI0_CFG_DATA_R; PCI0_CFG_DATA_R = -1; unsigned size = PCI0_CFG_DATA_R; if (size == 0 || addr == size) continue; size &= (addr & PCI_BAR_IO) ? ~PCI_BAR_IO_MASK : ~PCI_BAR_MEMORY_MASK; size = -size; pci_bar_t *bar = &pcidev->bar[pcidev->nbars++]; bar->addr = addr; bar->size = size; } pcibus->ndevs++; } } }
static char *make_pair(char *key, char *value) { int arglen = strlen(key) + strlen(value) + 2; char *arg = kernel_sbrk(arglen * sizeof(char)); strlcpy(arg, key, arglen); strlcat(arg, "=", arglen); strlcat(arg, value, arglen); return arg; }
/* Note that morecore has to take a signed argument so that negative values can return memory to the system. */ void * _default_morecore(long size) { void *result; result = kernel_sbrk(size); if (result == (void *) -1) return NULL; return result; }
/* * For some reason arguments passed to kernel are not correctly splitted * in argv array - in our case all arguments are stored in one string argv[1], * but we want to keep every argument in separate argv entry. This function * tokenize all argv strings and store every single token into individual entry * of new array. * * For our needs we also convert passed environment variables and put them * into new argv array. * * Example: * * For arguments: * argc=3; * argv={"test.elf", "arg1 arg2=val arg3=foobar ", " init=/bin/sh "}; * envp={"memsize", "128MiB", "uart.speed", "115200"}; * * instruction: * setup_kenv(argc, argv, envp); * * will set global variable _kenv as follows: * _kenv.argc=5; * _kenv.argv={"test.elf", "arg1", "arg2=val", "arg3=foobar", * "init=/bin/sh", "memsize=128MiB", "uart.speed=115200"}; */ static void setup_kenv(int argc, char **argv, char **envp) { unsigned ntokens = 0; for (int i = 0; i < argc; ++i) ntokens += count_tokens(argv[i]); for (char **pair = envp; *pair; pair += 2) ntokens++; _kenv.argc = ntokens; char **tokens = kernel_sbrk(ntokens * sizeof(char *)); _kenv.argv = tokens; for (int i = 0; i < argc; ++i) tokens = extract_tokens(argv[i], tokens); for (char **pair = envp; *pair; pair += 2) *tokens++ = make_pair(pair[0], pair[1]); }