mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Currently, xen.git#staging does not build in many environments because of issues with minios master. This regression was introduced in an uncontrolled manner by an update to mini-os.git#master. This is because ine013e85143"config: use mini-os master for unstable" we switched to tracking minios master in an uncontrolled manner. At the time we thought it was unlikely that minios changes would break the Xen build. This turns out to have been overly optimistic. Xen currently uses unstable internal interfaces of minios. Until this can be sorted out, internal changes to minios can require lockstep changes in Xen. All this means that "config: use mini-os master for unstable" was wrong. We should undo it. Instead, we go back to the previous situation: xen.git names a specific minios commit. This scheme is the model used for qemu-xen-traditional. That nailed commit must be updated manually, to have xen.git pick up changes from minios. If the minios changes require changes in xen.git too, to avoid breaking the Xen build, they can be made freely in minios without adverse consequences. When the minios commitid is updated in xen.git, the corresponding changes to the actual source files in xen.git should be bundled together. For example, when minios is fixed,8d990807ec"stubdom/grub: update init_netfront() call for mini-os" will need to be reapplied, folded into the same commit as updates MINIOS_UPSTREAM_REVISION. For now that commit must be reverted as we are going back to a previous version of minios. This reverts commit8d990807ec. This reverts commite013e85143. CC: Jan Beulich <jbeulich@suse.com> CC: Costin Lupu <costin.lupu@cs.pub.ro> CC: Wei Liu <wl@xen.org> CC: Samuel Thibault <samuel.thibault@ens-lyon.org> Signed-off-by: Ian Jackson <iwj@xenproject.org>
772 lines
16 KiB
C
772 lines
16 KiB
C
/*
|
|
* Mini-OS support for GRUB.
|
|
*
|
|
* Samuel Thibault <Samuel.Thibault@eu.citrix.com>, May 2008
|
|
*/
|
|
#include <sys/types.h>
|
|
#include <sys/time.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
#include <unistd.h>
|
|
|
|
#include <hypervisor.h>
|
|
#include <blkfront.h>
|
|
#include <netfront.h>
|
|
#include <fbfront.h>
|
|
#include <semaphore.h>
|
|
|
|
#include <osdep.h>
|
|
#include <shared.h>
|
|
#include <nic.h>
|
|
#include <etherboot.h>
|
|
#include <terminfo.h>
|
|
#include <term.h>
|
|
|
|
#include "mini-os.h"
|
|
|
|
extern const char *preset_menu;
|
|
char config_file[DEFAULT_FILE_BUFLEN] = "(hd0,0)/boot/grub/menu.lst";
|
|
unsigned long boot_drive = NETWORK_DRIVE;
|
|
unsigned long install_partition = 0xFFFFFF;
|
|
|
|
char version_string[] = VERSION;
|
|
|
|
/* Variables from asm.S */
|
|
int saved_entryno;
|
|
|
|
/*
|
|
* Disk
|
|
*/
|
|
|
|
struct blkfront_dev **blk_dev;
|
|
int blk_nb;
|
|
static struct blkfront_info *blk_info;
|
|
|
|
static int vbdcmp(const void *_vbd1, const void *_vbd2) {
|
|
char *vbd1 = *(char **)_vbd1;
|
|
char *vbd2 = *(char **)_vbd2;
|
|
int vbdn1 = atoi(vbd1);
|
|
int vbdn2 = atoi(vbd2);
|
|
return vbdn1 - vbdn2;
|
|
}
|
|
|
|
void init_disk (void)
|
|
{
|
|
char **list;
|
|
char *msg;
|
|
int i;
|
|
char *path;
|
|
|
|
msg = xenbus_ls(XBT_NIL, "device/vbd", &list);
|
|
if (msg) {
|
|
printk("Error %s while reading list of disks\n", msg);
|
|
free(msg);
|
|
return;
|
|
}
|
|
blk_nb = 0;
|
|
while (list[blk_nb])
|
|
blk_nb++;
|
|
blk_dev = malloc(blk_nb * sizeof(*blk_dev));
|
|
blk_info = malloc(blk_nb * sizeof(*blk_info));
|
|
|
|
qsort(list, blk_nb, sizeof(*list), vbdcmp);
|
|
|
|
for (i = 0; i < blk_nb; i++) {
|
|
printk("vbd %s is hd%d\n", list[i], i);
|
|
asprintf(&path, "device/vbd/%s", list[i]);
|
|
blk_dev[i] = init_blkfront(path, &blk_info[i]);
|
|
free(path);
|
|
free(list[i]);
|
|
}
|
|
}
|
|
|
|
/* Return the geometry of DRIVE in GEOMETRY. If an error occurs, return
|
|
non-zero, otherwise zero. */
|
|
int get_diskinfo (int drive, struct geometry *geometry)
|
|
{
|
|
int i;
|
|
if (!(drive & 0x80))
|
|
return -1;
|
|
|
|
i = drive - 0x80;
|
|
if (i >= blk_nb)
|
|
return -1;
|
|
|
|
/* Bogus geometry */
|
|
geometry->cylinders = 65535;
|
|
geometry->heads = 255;
|
|
geometry->sectors = 63;
|
|
|
|
geometry->total_sectors = blk_info[i].sectors;
|
|
geometry->sector_size = blk_info[i].sector_size;
|
|
geometry->flags = BIOSDISK_FLAG_LBA_EXTENSION;
|
|
if (blk_info[i].info & VDISK_CDROM)
|
|
geometry->flags |= BIOSDISK_FLAG_CDROM;
|
|
return 0;
|
|
}
|
|
|
|
/* Read/write NSEC sectors starting from SECTOR in DRIVE disk with GEOMETRY
|
|
from/into SEGMENT segment. If READ is BIOSDISK_READ, then read it,
|
|
else if READ is BIOSDISK_WRITE, then write it. If an geometry error
|
|
occurs, return BIOSDISK_ERROR_GEOMETRY, and if other error occurs, then
|
|
return the error number. Otherwise, return 0. */
|
|
int
|
|
biosdisk (int read, int drive, struct geometry *geometry,
|
|
unsigned int sector, int nsec, int segment)
|
|
{
|
|
void *addr = (void *) ((unsigned long)segment << 4);
|
|
struct blkfront_aiocb aiocb;
|
|
int i;
|
|
|
|
if (!(drive & 0x80))
|
|
return -1;
|
|
|
|
i = drive - 0x80;
|
|
if (i >= blk_nb)
|
|
return -1;
|
|
|
|
if (sector + nsec > geometry->total_sectors)
|
|
return -1;
|
|
|
|
aiocb.aio_dev = blk_dev[i];
|
|
aiocb.aio_buf = addr;
|
|
aiocb.aio_nbytes = (size_t)nsec * blk_info[i].sector_size;
|
|
aiocb.aio_offset = (off_t)sector * blk_info[i].sector_size;
|
|
aiocb.aio_cb = NULL;
|
|
|
|
blkfront_io(&aiocb, read == BIOSDISK_WRITE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
load_file(char *name, void **ptr, long *size)
|
|
{
|
|
char *buf = NULL;
|
|
int allocated = 1 * 1024 * 1024;
|
|
int len, filled = 0;
|
|
|
|
if (!grub_open (name))
|
|
return -1;
|
|
|
|
buf = malloc(allocated);
|
|
|
|
errnum = 0;
|
|
while (1) {
|
|
len = grub_read (buf + filled, allocated - filled);
|
|
if (! len) {
|
|
if (!errnum)
|
|
break;
|
|
grub_close ();
|
|
return -1;
|
|
}
|
|
filled += len;
|
|
if (filled < allocated)
|
|
break;
|
|
allocated *= 2;
|
|
buf = realloc(buf, allocated);
|
|
}
|
|
grub_close ();
|
|
*ptr = buf;
|
|
*size = filled;
|
|
return 0;
|
|
}
|
|
|
|
void *kernel_image, *module_image;
|
|
long kernel_size, module_size;
|
|
char *kernel_arg, *module_arg;
|
|
void *multiboot_next_module;
|
|
struct xen_multiboot_mod_list *multiboot_next_module_header;
|
|
|
|
kernel_t
|
|
load_image (char *kernel, char *arg, kernel_t suggested_type,
|
|
unsigned long load_flags)
|
|
{
|
|
arg = skip_to(0, arg);
|
|
if (kernel_image)
|
|
free(kernel_image);
|
|
kernel_image = NULL;
|
|
if (load_file (kernel, &kernel_image, &kernel_size))
|
|
return KERNEL_TYPE_NONE;
|
|
if (kernel_arg)
|
|
free(kernel_arg);
|
|
kernel_arg = strdup(arg);
|
|
return KERNEL_TYPE_PV;
|
|
}
|
|
|
|
int
|
|
load_initrd (char *initrd)
|
|
{
|
|
if (module_image)
|
|
free(module_image);
|
|
module_image = NULL;
|
|
multiboot_next_module = NULL;
|
|
multiboot_next_module_header = NULL;
|
|
load_file (initrd, &module_image, &module_size);
|
|
return ! errnum;
|
|
}
|
|
|
|
int
|
|
load_module (char *module, char *arg)
|
|
{
|
|
void *new_module, *new_module_image;
|
|
long new_module_size, rounded_new_module_size;
|
|
|
|
if (load_file (module, &new_module, &new_module_size))
|
|
return 0;
|
|
if (strlen(arg) >= PAGE_SIZE) {
|
|
/* Too big module command line */
|
|
errnum = ERR_WONT_FIT;
|
|
return 0;
|
|
}
|
|
rounded_new_module_size = (new_module_size + PAGE_SIZE - 1) & PAGE_MASK;
|
|
|
|
if (module_image && !multiboot_next_module_header) {
|
|
/* Initrd already loaded, drop it */
|
|
free(module_image);
|
|
if (module_arg)
|
|
free(module_arg);
|
|
module_image = NULL;
|
|
}
|
|
if (!module_image)
|
|
/* Reserve one page for the header */
|
|
multiboot_next_module = (void*) PAGE_SIZE;
|
|
|
|
/* Allocate more room for the new module plus its arg */
|
|
new_module_image = realloc(module_image,
|
|
(multiboot_next_module - module_image) + rounded_new_module_size + PAGE_SIZE);
|
|
|
|
/* Update pointers */
|
|
multiboot_next_module += new_module_image - module_image;
|
|
multiboot_next_module_header = (void*) multiboot_next_module_header + (new_module_image - module_image);
|
|
module_image = new_module_image;
|
|
|
|
if ((void*) (multiboot_next_module_header+1) - module_image > PAGE_SIZE) {
|
|
/* Too many modules */
|
|
errnum = ERR_WONT_FIT;
|
|
return 0;
|
|
}
|
|
|
|
/* Copy module */
|
|
memcpy(multiboot_next_module, new_module, new_module_size);
|
|
multiboot_next_module_header->mod_start = multiboot_next_module - module_image;
|
|
multiboot_next_module_header->mod_end = multiboot_next_module_header->mod_start + new_module_size - 1;
|
|
multiboot_next_module += rounded_new_module_size;
|
|
|
|
/* Copy cmdline */
|
|
strcpy(multiboot_next_module, arg);
|
|
multiboot_next_module_header->cmdline = multiboot_next_module - module_image;
|
|
multiboot_next_module += PAGE_SIZE;
|
|
|
|
/* Pad */
|
|
multiboot_next_module_header->pad = 0;
|
|
|
|
multiboot_next_module_header++;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
pv_boot (void)
|
|
{
|
|
unsigned long flags = 0;
|
|
if (multiboot_next_module_header) {
|
|
/* Termination entry */
|
|
multiboot_next_module_header->mod_start = 0;
|
|
/* Total size */
|
|
module_size = multiboot_next_module - module_image;
|
|
/* It's a multiboot module */
|
|
flags |= SIF_MULTIBOOT_MOD;
|
|
}
|
|
kexec(kernel_image, kernel_size, module_image, module_size, kernel_arg, flags);
|
|
}
|
|
|
|
/*
|
|
* Network
|
|
*/
|
|
|
|
struct netfront_dev *net_dev;
|
|
|
|
int
|
|
minios_probe (struct nic *nic)
|
|
{
|
|
char *ip;
|
|
|
|
if (net_dev)
|
|
return 1;
|
|
|
|
/* Clear the ARP table. */
|
|
grub_memset ((char *) arptable, 0,
|
|
MAX_ARP * sizeof (struct arptable_t));
|
|
|
|
net_dev = init_netfront(NULL, (void*) -1, nic->node_addr, &ip);
|
|
if (!net_dev)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* reset adapter */
|
|
static void minios_reset(struct nic *nic)
|
|
{
|
|
/* TODO? */
|
|
}
|
|
|
|
static void minios_disable(struct nic *nic)
|
|
{
|
|
}
|
|
|
|
/* Wait for a frame */
|
|
static int minios_poll(struct nic *nic)
|
|
{
|
|
return !! (nic->packetlen = netfront_receive(net_dev, (void*) nic->packet, ETH_FRAME_LEN));
|
|
}
|
|
|
|
/* Transmit a frame */
|
|
struct frame {
|
|
uint8_t dest[ETH_ALEN];
|
|
uint8_t src[ETH_ALEN];
|
|
uint16_t type;
|
|
unsigned char data[];
|
|
};
|
|
static void minios_transmit (struct nic *nic, const char *d, unsigned int t,
|
|
unsigned int s, const char *p)
|
|
{
|
|
struct frame *frame = alloca(sizeof(*frame) + s);
|
|
|
|
memcpy(frame->dest, d, ETH_ALEN);
|
|
memcpy(frame->src, nic->node_addr, ETH_ALEN);
|
|
frame->type = htons(t);
|
|
memcpy(frame->data, p, s);
|
|
|
|
netfront_xmit(net_dev, (void*) frame, sizeof(*frame) + s);
|
|
}
|
|
|
|
static char packet[ETH_FRAME_LEN];
|
|
|
|
struct nic nic = {
|
|
.reset = minios_reset,
|
|
.poll = minios_poll,
|
|
.transmit = minios_transmit,
|
|
.disable = minios_disable,
|
|
.flags = 0,
|
|
.rom_info = NULL,
|
|
.node_addr = arptable[ARP_CLIENT].node,
|
|
.packet = packet,
|
|
.packetlen = 0,
|
|
.priv_data = NULL,
|
|
};
|
|
|
|
int
|
|
eth_probe (void)
|
|
{
|
|
return minios_probe(&nic);
|
|
}
|
|
|
|
int
|
|
eth_poll (void)
|
|
{
|
|
return minios_poll (&nic);
|
|
}
|
|
|
|
void
|
|
eth_disable (void)
|
|
{
|
|
minios_disable (&nic);
|
|
}
|
|
|
|
void
|
|
eth_transmit (const char *d, unsigned int t,
|
|
unsigned int s, const void *p)
|
|
{
|
|
minios_transmit (&nic, d, t, s, p);
|
|
if (t == IP)
|
|
twiddle();
|
|
}
|
|
|
|
/*
|
|
* Console
|
|
*/
|
|
void
|
|
serial_hw_put (int _c)
|
|
{
|
|
char c = _c;
|
|
console_print(NULL, &c, 1);
|
|
}
|
|
|
|
int
|
|
serial_hw_fetch (void)
|
|
{
|
|
char key;
|
|
|
|
if (!xencons_ring_avail(NULL))
|
|
return -1;
|
|
|
|
read(STDIN_FILENO, &key, 1);
|
|
switch (key) {
|
|
case 0x7f: key = '\b'; break;
|
|
}
|
|
return key;
|
|
}
|
|
|
|
/*
|
|
* PVFB
|
|
*/
|
|
struct kbdfront_dev *kbd_dev;
|
|
struct fbfront_dev *fb_dev;
|
|
static union xenkbd_in_event ev;
|
|
static int has_ev;
|
|
int console_checkkey (void)
|
|
{
|
|
if (has_ev)
|
|
return 1;
|
|
has_ev = kbdfront_receive(kbd_dev, &ev, 1);
|
|
return has_ev;
|
|
}
|
|
|
|
/* static QWERTY layout, that's what most PC BIOSes do anyway */
|
|
static char linux2ascii[] = {
|
|
[ 1 ] = 27,
|
|
[ 2 ] = '1',
|
|
[ 3 ] = '2',
|
|
[ 4 ] = '3',
|
|
[ 5 ] = '4',
|
|
[ 6 ] = '5',
|
|
[ 7 ] = '6',
|
|
[ 8 ] = '7',
|
|
[ 9 ] = '8',
|
|
[ 10 ] = '9',
|
|
[ 11 ] = '0',
|
|
[ 12 ] = '-',
|
|
[ 13 ] = '=',
|
|
[ 14 ] = '\b',
|
|
[ 15 ] = '\t',
|
|
[ 16 ] = 'q',
|
|
[ 17 ] = 'w',
|
|
[ 18 ] = 'e',
|
|
[ 19 ] = 'r',
|
|
[ 20 ] = 't',
|
|
[ 21 ] = 'y',
|
|
[ 22 ] = 'u',
|
|
[ 23 ] = 'i',
|
|
[ 24 ] = 'o',
|
|
[ 25 ] = 'p',
|
|
[ 26 ] = '[',
|
|
[ 27 ] = ']',
|
|
[ 28 ] = '\n',
|
|
|
|
[ 30 ] = 'a',
|
|
[ 31 ] = 's',
|
|
[ 32 ] = 'd',
|
|
[ 33 ] = 'f',
|
|
[ 34 ] = 'g',
|
|
[ 35 ] = 'h',
|
|
[ 36 ] = 'j',
|
|
[ 37 ] = 'k',
|
|
[ 38 ] = 'l',
|
|
[ 39 ] = ';',
|
|
[ 40 ] = '\'',
|
|
[ 41 ] = '`',
|
|
|
|
[ 43 ] = '\\',
|
|
[ 44 ] = 'z',
|
|
[ 45 ] = 'x',
|
|
[ 46 ] = 'c',
|
|
[ 47 ] = 'v',
|
|
[ 48 ] = 'b',
|
|
[ 49 ] = 'n',
|
|
[ 50 ] = 'm',
|
|
[ 51 ] = ',',
|
|
[ 52 ] = '.',
|
|
[ 53 ] = '/',
|
|
|
|
[ 55 ] = '*',
|
|
[ 57 ] = ' ',
|
|
|
|
[ 71 ] = '7',
|
|
[ 72 ] = '8',
|
|
[ 73 ] = '9',
|
|
[ 74 ] = '-',
|
|
[ 75 ] = '4',
|
|
[ 76 ] = '5',
|
|
[ 77 ] = '6',
|
|
[ 78 ] = '+',
|
|
[ 79 ] = '1',
|
|
[ 80 ] = '2',
|
|
[ 81 ] = '3',
|
|
[ 82 ] = '0',
|
|
[ 83 ] = '.',
|
|
|
|
[ 86 ] = '<',
|
|
|
|
[ 96 ] = '\n',
|
|
|
|
[ 98 ] = '/',
|
|
|
|
[ 102 ] = 1, /* home */
|
|
[ 103 ] = 16, /* up */
|
|
[ 104 ] = 7, /* page up */
|
|
[ 105 ] = 2, /* left */
|
|
[ 106 ] = 6, /* right */
|
|
[ 107 ] = 5, /* end */
|
|
[ 108 ] = 14, /* down */
|
|
[ 109 ] = 3, /* page down */
|
|
|
|
[ 111 ] = 4, /* delete */
|
|
};
|
|
|
|
static char linux2ascii_shifted[] = {
|
|
[ 1 ] = 27,
|
|
[ 2 ] = '!',
|
|
[ 3 ] = '@',
|
|
[ 4 ] = '#',
|
|
[ 5 ] = '$',
|
|
[ 6 ] = '%',
|
|
[ 7 ] = '^',
|
|
[ 8 ] = '&',
|
|
[ 9 ] = '*',
|
|
[ 10 ] = '(',
|
|
[ 11 ] = ')',
|
|
[ 12 ] = '_',
|
|
[ 13 ] = '+',
|
|
[ 14 ] = '\b',
|
|
[ 15 ] = '\t',
|
|
[ 16 ] = 'Q',
|
|
[ 17 ] = 'W',
|
|
[ 18 ] = 'E',
|
|
[ 19 ] = 'R',
|
|
[ 20 ] = 'T',
|
|
[ 21 ] = 'Y',
|
|
[ 22 ] = 'U',
|
|
[ 23 ] = 'I',
|
|
[ 24 ] = 'O',
|
|
[ 25 ] = 'P',
|
|
[ 26 ] = '{',
|
|
[ 27 ] = '}',
|
|
[ 28 ] = '\n',
|
|
|
|
[ 30 ] = 'A',
|
|
[ 31 ] = 'S',
|
|
[ 32 ] = 'D',
|
|
[ 33 ] = 'F',
|
|
[ 34 ] = 'G',
|
|
[ 35 ] = 'H',
|
|
[ 36 ] = 'J',
|
|
[ 37 ] = 'K',
|
|
[ 38 ] = 'L',
|
|
[ 39 ] = ':',
|
|
[ 40 ] = '"',
|
|
[ 41 ] = '~',
|
|
|
|
[ 43 ] = '|',
|
|
[ 44 ] = 'Z',
|
|
[ 45 ] = 'X',
|
|
[ 46 ] = 'C',
|
|
[ 47 ] = 'V',
|
|
[ 48 ] = 'B',
|
|
[ 49 ] = 'N',
|
|
[ 50 ] = 'M',
|
|
[ 51 ] = '<',
|
|
[ 52 ] = '>',
|
|
[ 53 ] = '?',
|
|
|
|
[ 55 ] = '*',
|
|
[ 57 ] = ' ',
|
|
|
|
[ 71 ] = '7',
|
|
[ 72 ] = '8',
|
|
[ 73 ] = '9',
|
|
[ 74 ] = '-',
|
|
[ 75 ] = '4',
|
|
[ 76 ] = '5',
|
|
[ 77 ] = '6',
|
|
[ 78 ] = '+',
|
|
[ 79 ] = '1',
|
|
[ 80 ] = '2',
|
|
[ 81 ] = '3',
|
|
[ 82 ] = '0',
|
|
[ 83 ] = '.',
|
|
|
|
[ 86 ] = '>',
|
|
|
|
[ 96 ] = '\n',
|
|
|
|
[ 98 ] = '/',
|
|
|
|
[ 102 ] = 1, /* home */
|
|
[ 103 ] = 16, /* up */
|
|
[ 104 ] = 7, /* page up */
|
|
[ 105 ] = 2, /* left */
|
|
[ 106 ] = 6, /* right */
|
|
[ 107 ] = 5, /* end */
|
|
[ 108 ] = 14, /* down */
|
|
[ 109 ] = 3, /* page down */
|
|
|
|
[ 111 ] = 4, /* delete */
|
|
};
|
|
|
|
int console_getkey (void)
|
|
{
|
|
static int shift, control, alt, caps_lock;
|
|
|
|
if (!has_ev)
|
|
has_ev = kbdfront_receive(kbd_dev, &ev, 1);
|
|
if (!has_ev)
|
|
return 0;
|
|
|
|
has_ev = 0;
|
|
if (ev.type != XENKBD_TYPE_KEY)
|
|
return 0;
|
|
|
|
if (ev.key.keycode == 42 || ev.key.keycode == 54) {
|
|
caps_lock = 0;
|
|
shift = ev.key.pressed;
|
|
return 0;
|
|
}
|
|
if (ev.key.keycode == 58) {
|
|
caps_lock ^= 1;
|
|
return 0;
|
|
}
|
|
if (ev.key.keycode == 29 || ev.key.keycode == 97) {
|
|
control = ev.key.pressed;
|
|
return 0;
|
|
}
|
|
if (ev.key.keycode == 56) {
|
|
alt = ev.key.pressed;
|
|
return 0;
|
|
}
|
|
|
|
if (!ev.key.pressed)
|
|
return 0;
|
|
|
|
if (ev.key.keycode < sizeof(linux2ascii) / sizeof(*linux2ascii)) {
|
|
char val;
|
|
if (shift || caps_lock)
|
|
val = linux2ascii_shifted[ev.key.keycode];
|
|
else
|
|
val = linux2ascii[ev.key.keycode];
|
|
if (control)
|
|
val &= ~0x60;
|
|
return val;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static DECLARE_MUTEX_LOCKED(kbd_sem);
|
|
static void kbd_thread(void *p)
|
|
{
|
|
kbd_dev = init_kbdfront(NULL, 1);
|
|
up(&kbd_sem);
|
|
}
|
|
|
|
struct fbfront_dev *fb_open(void *fb, int width, int height, int depth)
|
|
{
|
|
unsigned long *mfns;
|
|
int linesize = width * (depth / 8);
|
|
int memsize = linesize * height;
|
|
int numpages = (memsize + PAGE_SIZE - 1) / PAGE_SIZE;
|
|
int i;
|
|
|
|
create_thread("kbdfront", kbd_thread, &kbd_sem);
|
|
|
|
mfns = malloc(numpages * sizeof(*mfns));
|
|
for (i = 0; i < numpages; i++) {
|
|
memset(fb + i * PAGE_SIZE, 0, PAGE_SIZE);
|
|
mfns[i] = virtual_to_mfn(fb + i * PAGE_SIZE);
|
|
}
|
|
fb_dev = init_fbfront(NULL, mfns, width, height, depth, linesize, numpages);
|
|
free(mfns);
|
|
|
|
if (!fb_dev)
|
|
return NULL;
|
|
|
|
down(&kbd_sem);
|
|
if (!kbd_dev)
|
|
return NULL;
|
|
|
|
return fb_dev;
|
|
}
|
|
|
|
void kbd_close(void *foo)
|
|
{
|
|
shutdown_kbdfront(kbd_dev);
|
|
kbd_dev = NULL;
|
|
}
|
|
|
|
void fb_close(void)
|
|
{
|
|
create_thread("kbdfront close", kbd_close, NULL);
|
|
shutdown_fbfront(fb_dev);
|
|
fb_dev = NULL;
|
|
}
|
|
|
|
/*
|
|
* Misc
|
|
*/
|
|
|
|
int getrtsecs (void)
|
|
{
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
return tv.tv_sec % 10 + ((tv.tv_sec / 10) % 6) * 0x10;
|
|
}
|
|
|
|
int currticks (void)
|
|
{
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
return ((tv.tv_sec * 1000000ULL + tv.tv_usec) * TICKS_PER_SEC) / 1000000;
|
|
}
|
|
|
|
void __attribute__ ((noreturn)) grub_reboot (void)
|
|
{
|
|
for ( ;; )
|
|
{
|
|
struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_reboot };
|
|
HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
|
|
}
|
|
}
|
|
|
|
#define SCRATCH_MEMSIZE (4 * 1024 * 1024)
|
|
|
|
/* Note: not allocating it dynamically permits to make sure it lays below 4G
|
|
* for grub's 32bit pointers to work */
|
|
char grub_scratch_mem[SCRATCH_MEMSIZE] __attribute__((aligned(PAGE_SIZE)));
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc > 1 && memcmp(argv[1], "--vtpm-label=", 13) == 0) {
|
|
vtpm_label = argv[1] + 13;
|
|
argc--;
|
|
argv++;
|
|
}
|
|
|
|
if (argc > 1) {
|
|
strncpy(config_file, argv[1], sizeof(config_file) - 1);
|
|
config_file[sizeof(config_file) - 1] = 0;
|
|
if (!strncmp(config_file, "(nd)", 4))
|
|
preset_menu = "dhcp";
|
|
} else if (start_info.mod_len)
|
|
preset_menu = (void*) start_info.mod_start;
|
|
else
|
|
preset_menu = "dhcp --with-configfile";
|
|
|
|
mbi.drives_addr = BOOTSEC_LOCATION + (60 * 1024);
|
|
mbi.drives_length = 0;
|
|
|
|
mbi.boot_loader_name = (unsigned long) "GNU GRUB " VERSION;
|
|
mbi.mem_lower = (start_info.nr_pages * PAGE_SIZE) / 1024;
|
|
mbi.mem_upper = 0;
|
|
saved_drive = boot_drive;
|
|
saved_partition = install_partition;
|
|
|
|
init_disk();
|
|
|
|
/* Try to make sure the client part got launched */
|
|
sleep(1);
|
|
cmain();
|
|
printk("cmain returned!\n");
|
|
}
|