[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

porting Grub to Xen

From: Ferenc Wagner
Subject: porting Grub to Xen
Date: Mon, 18 May 2009 20:45:08 +0200
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux)


Last week we had a very interesting chat on #grub, discussing various
possibilities to run Grub in a Xen paravirtual domain.  You showed
some interest in properly porting Grub to this architecture instead of
my misguided attempts to go through grub-emu and kexec.  You asked for
the interface docs to be able to assess the task.  Please find it under

referenced as "Developer Manual" in HTML and PDF.  I put online the
current MiniOS source at, which is
bundled with Xen, and provides a running example of the interface
specification.  Porting could mean taking the necessary parts or this,
and adding the Grub interface.  Please find attached my current disk
interface, which works under grub-emu (under MiniOS).

So, what do you think about this?  I'm afraid I don't have the
necessary low-level knowledge to be of much help starting, but at
least have a definite need, so I'll try my best.


#include <grub/disk.h>

#include <grub/util/xendisk.h>

/* Parts stolen from stubdom/grub/mini-os.c */

#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <assert.h>

#include <hypervisor.h>
#include <blkfront.h>

unsigned int blk_nb;
struct blkfront_dev **blk_dev;
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;

static unsigned int
init_disk (void)
    char **list;
    char *msg;
    unsigned int i;
    char *path;

    msg = xenbus_ls(XBT_NIL, "device/vbd", &list);
    if (msg) {
        printk("Error %s while reading list of disks\n", msg);
        return 0;
    blk_nb = 0;
    while (list[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]);
    return blk_nb;

static grub_err_t
read_sectors (unsigned int drive, void *data, size_t count, off_t from)
        struct blkfront_aiocb aio;

        if (drive >= blk_nb) return GRUB_ERR_UNKNOWN_DEVICE;

        aio.aio_dev = blk_dev[drive];
        aio.aio_buf = data;
        aio.aio_nbytes = count * blk_info[drive].sector_size;
        aio.aio_offset =  from * blk_info[drive].sector_size;
        aio.aio_cb = NULL;
        blkfront_read (&aio);
        return GRUB_ERR_NONE; /* FIXME report error */

/* Grub interface */

static int
grub_util_xendisk_iterate (int (*hook) (const char *name))
    unsigned int i;
    char buf[10];

    for (i = 0; i < blk_nb; i++) {
        int ret;

        snprintf (buf, sizeof buf, "%d", i);
        ret = hook (buf);
        if (ret) return 1;
    return 0;

static grub_err_t
grub_util_xendisk_open (const char *name, grub_disk_t disk)
    unsigned int drive = atoi (name);

    if (drive >= blk_nb) return GRUB_ERR_UNKNOWN_DEVICE;
    disk->has_partitions = 0;
    disk->id = drive;
    disk->total_sectors = blk_info[drive].sectors;
    return GRUB_ERR_NONE;

char buffer[GRUB_DISK_SECTOR_SIZE] __attribute__((aligned(PAGE_SIZE)));

static grub_err_t
grub_util_xendisk_read (grub_disk_t disk, grub_disk_addr_t sector,
                        grub_size_t count, char *buf)
    grub_size_t i;

    for (i=0; i<count; i++) {
        if (read_sectors (disk->id, buffer, 1, sector+i))
            return GRUB_ERR_READ_ERROR;
        memcpy (buf+i*GRUB_DISK_SECTOR_SIZE, buffer, GRUB_DISK_SECTOR_SIZE);
    return GRUB_ERR_NONE;


static struct grub_disk_dev grub_util_xendisk_dev = {
    .name = "xendisk",
    .iterate = grub_util_xendisk_iterate,
    .open = grub_util_xendisk_open,
    .close = 0,
    .read = grub_util_xendisk_read,
    .write = 0,
    .next = 0

grub_util_xendisk_init ()
    grub_disk_dev_register (&grub_util_xendisk_dev);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]