199767f8919635c4928607450d9e0abb932109ceToomas Soome/*-
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 2008 John Hay
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (c) 1998 Robert Nordier
199767f8919635c4928607450d9e0abb932109ceToomas Soome * All rights reserved.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Redistribution and use in source and binary forms are freely
199767f8919635c4928607450d9e0abb932109ceToomas Soome * permitted provided that the above copyright notice and this
199767f8919635c4928607450d9e0abb932109ceToomas Soome * paragraph and the following disclaimer are duplicated in all
199767f8919635c4928607450d9e0abb932109ceToomas Soome * such forms.
199767f8919635c4928607450d9e0abb932109ceToomas Soome *
199767f8919635c4928607450d9e0abb932109ceToomas Soome * This software is provided "AS IS" and without any express or
199767f8919635c4928607450d9e0abb932109ceToomas Soome * implied warranties, including, without limitation, the implied
199767f8919635c4928607450d9e0abb932109ceToomas Soome * warranties of merchantability and fitness for a particular
199767f8919635c4928607450d9e0abb932109ceToomas Soome * purpose.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/cdefs.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome__FBSDID("$FreeBSD$");
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/param.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/disklabel.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/diskmbr.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/dirent.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <sys/reboot.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <machine/elf.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include <stdarg.h>
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "lib.h"
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "paths.h"
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "rbx.h"
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomeextern uint32_t _end;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define NOPT 6
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic const char optstr[NOPT] = "agnrsv";
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic const unsigned char flags[NOPT] = {
199767f8919635c4928607450d9e0abb932109ceToomas Soome RBX_ASKNAME,
199767f8919635c4928607450d9e0abb932109ceToomas Soome RBX_GDB,
199767f8919635c4928607450d9e0abb932109ceToomas Soome RBX_NOINTR,
199767f8919635c4928607450d9e0abb932109ceToomas Soome RBX_DFLTROOT,
199767f8919635c4928607450d9e0abb932109ceToomas Soome RBX_SINGLE,
199767f8919635c4928607450d9e0abb932109ceToomas Soome RBX_VERBOSE
199767f8919635c4928607450d9e0abb932109ceToomas Soome};
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic unsigned dsk_start;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic char cmd[512];
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic char kname[1024];
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic uint32_t opts;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic uint8_t dsk_meta;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int bootslice;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int bootpart;
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int disk_layout;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define DL_UNKNOWN 0
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define DL_RAW 1 /* Dangerously dedicated */
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define DL_SLICE 2 /* Use only slices (DOS partitions) */
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define DL_SLICEPART 3 /* Use slices and partitions */
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void load(void);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int parse(void);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int dskread(void *, unsigned, unsigned);
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int drvread(void *, unsigned, unsigned);
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef FIXUP_BOOT_DRV
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void fixup_boot_drv(caddr_t, int, int, int);
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#include "ufsread.c"
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef DEBUG
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define DPRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
199767f8919635c4928607450d9e0abb932109ceToomas Soome#else
199767f8919635c4928607450d9e0abb932109ceToomas Soome#define DPRINTF(fmt, ...)
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic inline int
199767f8919635c4928607450d9e0abb932109ceToomas Soomexfsread(ufs_ino_t inode, void *buf, size_t nbyte)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((size_t)fsread(inode, buf, nbyte) != nbyte)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return -1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic inline void
199767f8919635c4928607450d9e0abb932109ceToomas Soomegetstr(int c)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *s;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome s = cmd;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (c == 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome c = getc(10000);
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (;;) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome switch (c) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome case 0:
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome case '\177':
199767f8919635c4928607450d9e0abb932109ceToomas Soome case '\b':
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (s > cmd) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome s--;
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("\b \b");
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome case '\n':
199767f8919635c4928607450d9e0abb932109ceToomas Soome case '\r':
199767f8919635c4928607450d9e0abb932109ceToomas Soome *s = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome default:
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (s - cmd < sizeof(cmd) - 1)
199767f8919635c4928607450d9e0abb932109ceToomas Soome *s++ = c;
199767f8919635c4928607450d9e0abb932109ceToomas Soome xputchar(c);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome c = getc(10000);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint
199767f8919635c4928607450d9e0abb932109ceToomas Soomemain(void)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome const char *bt;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int autoboot, c = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome ufs_ino_t ino;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome dmadat = (void *)(0x1c0000);
199767f8919635c4928607450d9e0abb932109ceToomas Soome p_memset((char *)dmadat, 0, 32 * 1024);
199767f8919635c4928607450d9e0abb932109ceToomas Soome bt = board_init();
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("FreeBSD ARM (%s) boot2 v%d.%d\n", bt, 0, 4);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome autoboot = 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Process configuration file */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((ino = lookup(PATH_CONFIG)) ||
199767f8919635c4928607450d9e0abb932109ceToomas Soome (ino = lookup(PATH_DOTCONFIG)))
199767f8919635c4928607450d9e0abb932109ceToomas Soome fsread(ino, cmd, sizeof(cmd));
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*cmd) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (parse())
199767f8919635c4928607450d9e0abb932109ceToomas Soome autoboot = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("%s: %s\n", PATH_CONFIG, cmd);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Do not process this command twice */
199767f8919635c4928607450d9e0abb932109ceToomas Soome *cmd = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*kname == '\0')
199767f8919635c4928607450d9e0abb932109ceToomas Soome strcpy(kname, PATH_KERNEL);
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* Present the user with the boot2 prompt. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (;;) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("\nDefault: %s\nboot: ", kname);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!autoboot ||
199767f8919635c4928607450d9e0abb932109ceToomas Soome (OPT_CHECK(RBX_NOINTR) == 0 && (c = getc(2)) != 0))
199767f8919635c4928607450d9e0abb932109ceToomas Soome getstr(c);
199767f8919635c4928607450d9e0abb932109ceToomas Soome xputchar('\n');
199767f8919635c4928607450d9e0abb932109ceToomas Soome autoboot = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome c = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("cmd is '%s'\n", cmd);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (parse())
199767f8919635c4928607450d9e0abb932109ceToomas Soome xputchar('\a');
199767f8919635c4928607450d9e0abb932109ceToomas Soome else
199767f8919635c4928607450d9e0abb932109ceToomas Soome load();
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void
199767f8919635c4928607450d9e0abb932109ceToomas Soomeload(void)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome Elf32_Ehdr eh;
199767f8919635c4928607450d9e0abb932109ceToomas Soome static Elf32_Phdr ep[2];
199767f8919635c4928607450d9e0abb932109ceToomas Soome caddr_t p;
199767f8919635c4928607450d9e0abb932109ceToomas Soome ufs_ino_t ino;
199767f8919635c4928607450d9e0abb932109ceToomas Soome uint32_t addr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int i, j;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef FIXUP_BOOT_DRV
199767f8919635c4928607450d9e0abb932109ceToomas Soome caddr_t staddr;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int klen;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome staddr = (caddr_t)0xffffffff;
199767f8919635c4928607450d9e0abb932109ceToomas Soome klen = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!(ino = lookup(kname))) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!ls)
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("No %s\n", kname);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("Found %s\n", kname);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (xfsread(ino, &eh, sizeof(eh)))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!IS_ELF(eh)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("Invalid %s\n", "format");
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs_off = eh.e_phoff;
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (j = i = 0; i < eh.e_phnum && j < 2; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (xfsread(ino, ep + j, sizeof(ep[0])))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ep[j].p_type == PT_LOAD)
199767f8919635c4928607450d9e0abb932109ceToomas Soome j++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < 2; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome p = (caddr_t)(ep[i].p_paddr & 0x0fffffff);
199767f8919635c4928607450d9e0abb932109ceToomas Soome fs_off = ep[i].p_offset;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef FIXUP_BOOT_DRV
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (staddr == (caddr_t)0xffffffff)
199767f8919635c4928607450d9e0abb932109ceToomas Soome staddr = p;
199767f8919635c4928607450d9e0abb932109ceToomas Soome klen += ep[i].p_filesz;
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (xfsread(ino, p, ep[i].p_filesz))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome addr = eh.e_entry & 0x0fffffff;
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("Entry point %x for %s\n", addr, kname);
199767f8919635c4928607450d9e0abb932109ceToomas Soome clr_board();
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef FIXUP_BOOT_DRV
199767f8919635c4928607450d9e0abb932109ceToomas Soome fixup_boot_drv(staddr, klen, bootslice, bootpart);
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif
199767f8919635c4928607450d9e0abb932109ceToomas Soome ((void(*)(int))addr)(RB_BOOTINFO /* XXX | (opts & RBX_MASK) */);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomeparse()
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *arg = cmd;
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *ep, *p;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int c, i;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome while ((c = *arg++)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (c == ' ' || c == '\t' || c == '\n')
199767f8919635c4928607450d9e0abb932109ceToomas Soome continue;
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
199767f8919635c4928607450d9e0abb932109ceToomas Soome ep = p;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*p)
199767f8919635c4928607450d9e0abb932109ceToomas Soome *p++ = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (c == '-') {
199767f8919635c4928607450d9e0abb932109ceToomas Soome while ((c = *arg++)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; c != optstr[i]; i++)
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (i == NOPT - 1)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return -1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome opts ^= OPT_SET(flags[i]);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome arg--;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* look for ad0s1a:... | ad0s1:... */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (strlen(arg) > 6 && arg[0] == 'a' &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome arg[1] == 'd' && arg[3] == 's' &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome (arg[5] == ':' || arg[6] == ':')) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* XXX Should also handle disk. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome bootslice = arg[4] - '0';
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bootslice < 1 || bootslice > 4)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome bootpart = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (arg[5] != ':')
199767f8919635c4928607450d9e0abb932109ceToomas Soome bootpart = arg[5] - 'a';
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bootpart < 0 || bootpart > 7)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome dsk_meta = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (arg[5] == ':')
199767f8919635c4928607450d9e0abb932109ceToomas Soome arg += 6;
199767f8919635c4928607450d9e0abb932109ceToomas Soome else
199767f8919635c4928607450d9e0abb932109ceToomas Soome arg += 7;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* look for ad0a:... */
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else if (strlen(arg) > 4 && arg[0] == 'a' &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome arg[1] == 'd' && arg[2] == '0' && arg[4] == ':') {
199767f8919635c4928607450d9e0abb932109ceToomas Soome bootslice = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bootpart = arg[3] - 'a';
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bootpart < 0 || bootpart > 7)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (-1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome dsk_meta = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome arg += 5;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((i = ep - arg)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((size_t)i >= sizeof(kname))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return -1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome memcpy(kname, arg, i + 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome arg = p;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * dskread() will try to handle the disk layouts that are typically
199767f8919635c4928607450d9e0abb932109ceToomas Soome * encountered.
199767f8919635c4928607450d9e0abb932109ceToomas Soome * - raw or "Dangerously Dedicated" mode. No real slice table, just the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * default one that is included with bsdlabel -B. Typically this is
199767f8919635c4928607450d9e0abb932109ceToomas Soome * used with ROOTDEVNAME=\"ufs:ad0a\".
199767f8919635c4928607450d9e0abb932109ceToomas Soome * - slice only. Only a slice table is installed with no bsd label or
199767f8919635c4928607450d9e0abb932109ceToomas Soome * bsd partition table. This is typically used with
199767f8919635c4928607450d9e0abb932109ceToomas Soome * ROOTDEVNAME=\"ufs:ad0s1\".
199767f8919635c4928607450d9e0abb932109ceToomas Soome * - slice + bsd label + partition table. This is typically done with
199767f8919635c4928607450d9e0abb932109ceToomas Soome * with fdisk + bsdlabel and is used with ROOTDEVNAME=\"ufs:ad0s1a\".
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomedskread(void *buf, unsigned lba, unsigned nblk)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct dos_partition *dp;
199767f8919635c4928607450d9e0abb932109ceToomas Soome struct disklabel *d;
199767f8919635c4928607450d9e0abb932109ceToomas Soome char *sec;
199767f8919635c4928607450d9e0abb932109ceToomas Soome int i;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!dsk_meta) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome sec = dmadat->secbuf;
199767f8919635c4928607450d9e0abb932109ceToomas Soome dsk_start = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (drvread(sec, DOSBBSECTOR, 1))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return -1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome dp = (void *)(sec + DOSPARTOFF);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bootslice != 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome i = bootslice - 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (dp[i].dp_typ != DOSPTYP_386BSD)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return -1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome for (i = 0; i < NDOSPART; i++) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((dp[i].dp_typ == DOSPTYP_386BSD) &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome (dp[i].dp_flag == 0x80))
199767f8919635c4928607450d9e0abb932109ceToomas Soome break;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (i != NDOSPART) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome bootslice = i + 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("Found an active fbsd slice. (%d)\n", i + 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Although dp_start is aligned within the disk
199767f8919635c4928607450d9e0abb932109ceToomas Soome * partition structure, DOSPARTOFF is 446, which
199767f8919635c4928607450d9e0abb932109ceToomas Soome * is only word (2) aligned, not longword (4)
199767f8919635c4928607450d9e0abb932109ceToomas Soome * aligned. Cope by using memcpy to fetch the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * start of this partition.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soome memcpy(&dsk_start, &dp[i].dp_start, 4);
199767f8919635c4928607450d9e0abb932109ceToomas Soome dsk_start = swap32(dsk_start);
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("dsk_start %x\n", dsk_start);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((bootslice == 4) && (dsk_start == 0)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome disk_layout = DL_RAW;
199767f8919635c4928607450d9e0abb932109ceToomas Soome bootslice = 0;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (drvread(sec, dsk_start + LABELSECTOR, 1))
199767f8919635c4928607450d9e0abb932109ceToomas Soome return -1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome d = (void *)(sec + LABELOFFSET);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((d->d_magic == DISKMAGIC && d->d_magic2 == DISKMAGIC) ||
199767f8919635c4928607450d9e0abb932109ceToomas Soome (swap32(d->d_magic) == DISKMAGIC &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome swap32(d->d_magic2) == DISKMAGIC)) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("p_size = %x\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome !d->d_partitions[bootpart].p_size);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (!d->d_partitions[bootpart].p_size) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("Invalid partition\n");
199767f8919635c4928607450d9e0abb932109ceToomas Soome return -1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("p_offset %x, RAW %x\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome swap32(d->d_partitions[bootpart].p_offset),
199767f8919635c4928607450d9e0abb932109ceToomas Soome swap32(d->d_partitions[RAW_PART].p_offset));
199767f8919635c4928607450d9e0abb932109ceToomas Soome dsk_start += swap32(d->d_partitions[bootpart].p_offset);
199767f8919635c4928607450d9e0abb932109ceToomas Soome dsk_start -= swap32(d->d_partitions[RAW_PART].p_offset);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((disk_layout == DL_UNKNOWN) && (bootslice == 0))
199767f8919635c4928607450d9e0abb932109ceToomas Soome disk_layout = DL_RAW;
199767f8919635c4928607450d9e0abb932109ceToomas Soome else if (disk_layout == DL_UNKNOWN)
199767f8919635c4928607450d9e0abb932109ceToomas Soome disk_layout = DL_SLICEPART;
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome disk_layout = DL_SLICE;
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("Invalid %s\n", "label");
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("bootslice %d, bootpart %d, dsk_start %u\n", bootslice,
199767f8919635c4928607450d9e0abb932109ceToomas Soome bootpart, dsk_start);
199767f8919635c4928607450d9e0abb932109ceToomas Soome dsk_meta++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome return drvread(buf, dsk_start + lba, nblk);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic int
199767f8919635c4928607450d9e0abb932109ceToomas Soomedrvread(void *buf, unsigned lba, unsigned nblk)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome static unsigned c = 0x2d5c7c2f;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("%c\b", c = c << 8 | c >> 24);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (avila_read((char *)buf, lba, nblk));
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome#ifdef FIXUP_BOOT_DRV
199767f8919635c4928607450d9e0abb932109ceToomas Soome/*
199767f8919635c4928607450d9e0abb932109ceToomas Soome * fixup_boot_drv() will try to find the ROOTDEVNAME spec in the kernel
199767f8919635c4928607450d9e0abb932109ceToomas Soome * and change it to what was specified on the comandline or /boot.conf
199767f8919635c4928607450d9e0abb932109ceToomas Soome * file or to what was encountered on the disk. It will try to handle 3
199767f8919635c4928607450d9e0abb932109ceToomas Soome * different disk layouts, raw (dangerously dedicated), slice only and
199767f8919635c4928607450d9e0abb932109ceToomas Soome * slice + partition. It will look for the following strings in the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * kernel, but if it is one of the first three, the string in the kernel
199767f8919635c4928607450d9e0abb932109ceToomas Soome * must use the correct form to match the actual disk layout:
199767f8919635c4928607450d9e0abb932109ceToomas Soome * - ufs:ad0a
199767f8919635c4928607450d9e0abb932109ceToomas Soome * - ufs:ad0s1
199767f8919635c4928607450d9e0abb932109ceToomas Soome * - ufs:ad0s1a
199767f8919635c4928607450d9e0abb932109ceToomas Soome * - ufs:ROOTDEVNAME
199767f8919635c4928607450d9e0abb932109ceToomas Soome * In the case of the first three strings, only the "a" at the end and
199767f8919635c4928607450d9e0abb932109ceToomas Soome * the "1" after the "s" will be modified, if they exist. The string
199767f8919635c4928607450d9e0abb932109ceToomas Soome * length will not be changed. In the case of the last string, the
199767f8919635c4928607450d9e0abb932109ceToomas Soome * whole string will be built up and nul, '\0' terminated.
199767f8919635c4928607450d9e0abb932109ceToomas Soome */
199767f8919635c4928607450d9e0abb932109ceToomas Soomestatic void
199767f8919635c4928607450d9e0abb932109ceToomas Soomefixup_boot_drv(caddr_t addr, int klen, int bs, int bp)
199767f8919635c4928607450d9e0abb932109ceToomas Soome{
199767f8919635c4928607450d9e0abb932109ceToomas Soome const u_int8_t op[] = "ufs:ROOTDEVNAME";
199767f8919635c4928607450d9e0abb932109ceToomas Soome const u_int8_t op2[] = "ufs:ad0";
199767f8919635c4928607450d9e0abb932109ceToomas Soome u_int8_t *p, *ps;
199767f8919635c4928607450d9e0abb932109ceToomas Soome
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("fixup_boot_drv: 0x%x, %d, slice %d, partition %d\n",
199767f8919635c4928607450d9e0abb932109ceToomas Soome (int)addr, klen, bs, bp);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bs > 4)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bp > 7)
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome ps = memmem(addr, klen, op, sizeof(op));
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ps != NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome p = ps + 4; /* past ufs: */
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("Found it at 0x%x\n", (int)ps);
199767f8919635c4928607450d9e0abb932109ceToomas Soome p[0] = 'a'; p[1] = 'd'; p[2] = '0'; /* ad0 */
199767f8919635c4928607450d9e0abb932109ceToomas Soome p += 3;
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (bs > 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* append slice */
199767f8919635c4928607450d9e0abb932109ceToomas Soome *p++ = 's';
199767f8919635c4928607450d9e0abb932109ceToomas Soome *p++ = bs + '0';
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (disk_layout != DL_SLICE) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* append partition */
199767f8919635c4928607450d9e0abb932109ceToomas Soome *p++ = bp + 'a';
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome *p = '\0';
199767f8919635c4928607450d9e0abb932109ceToomas Soome } else {
199767f8919635c4928607450d9e0abb932109ceToomas Soome ps = memmem(addr, klen, op2, sizeof(op2) - 1);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ps != NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome p = ps + sizeof(op2) - 1;
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("Found it at 0x%x\n", (int)ps);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*p == 's') {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* fix slice */
199767f8919635c4928607450d9e0abb932109ceToomas Soome p++;
199767f8919635c4928607450d9e0abb932109ceToomas Soome *p++ = bs + '0';
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (*p == 'a')
199767f8919635c4928607450d9e0abb932109ceToomas Soome *p = bp + 'a';
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (ps == NULL) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome printf("Could not locate \"%s\" to fix kernel boot device, "
199767f8919635c4928607450d9e0abb932109ceToomas Soome "check ROOTDEVNAME is set\n", op);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return;
199767f8919635c4928607450d9e0abb932109ceToomas Soome }
199767f8919635c4928607450d9e0abb932109ceToomas Soome DPRINTF("Changed boot device to %s\n", ps);
199767f8919635c4928607450d9e0abb932109ceToomas Soome}
199767f8919635c4928607450d9e0abb932109ceToomas Soome#endif