Hi, 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
http://www.cl.cam.ac.uk/research/srg/netos/xen/documentation.html referenced as "Developer Manual" in HTML and PDF. I put online the current MiniOS source at http://apt.niif.hu/minios.tgz, 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. Thanks, Feri.
#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); free(msg); return 0; } 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 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", .id = GRUB_DISK_DEVICE_XEN_ID, .iterate = grub_util_xendisk_iterate, .open = grub_util_xendisk_open, .close = 0, .read = grub_util_xendisk_read, .write = 0, .next = 0 }; void grub_util_xendisk_init () { grub_disk_dev_register (&grub_util_xendisk_dev); }
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel