[SeaBIOS] [PATCH 0/9] Misc boot related cleanups

Gleb Natapov gleb at redhat.com
Thu Dec 30 07:01:15 CET 2010


On Wed, Dec 29, 2010 at 08:23:13PM -0500, Kevin O'Connor wrote:
> On Wed, Dec 29, 2010 at 10:29:57PM +0200, Gleb Natapov wrote:
> > On Wed, Dec 29, 2010 at 02:10:16PM -0500, Kevin O'Connor wrote:
> > > BTW, I was thinking of ways to try and simplify this code.  What if we
> > > tried doing an exact string match for the device, but if that fails
> > > and a BDF is known for the device then do a prefix string search for
> > > the PCI device?
> > > 
> > I don't see why this would be simpler. Also how can you do exact string
> > match if BDF is not knows? You can't create device path without knowing
> > BDF (well DF). My code works like OpenFirmware device path was designed
> > to work: match device path one node at a time. This also allows for
> > greater flexibility in qemu<->seabios interface.
> 
> Playing around with this a little further, I came up with the below.
> I'm not sure if it's better.
> 
For me it looks more complicated (may be because I am more familiar with
my own code ;)) I see that you are starting to add regular expressions
engine!

> I added a "magic" syntax to support rom instances (eg,
> /rom2 at genroms/linuxboot.bin, /pci at i0cf8/scsi at 3/rom2).  I also stubbed
> out some (admittedly wrong) pci bus path support.
> 
For supporting multiple pci buses we need to keep track of pci bus
topology in upper layers. Bus number in bdf is meaningless for device
path purposes. Just drop this code for good.

To boot from a certain file on a device OpenFirmware uses following
syntax: /path/to/device:filename i.e parameter goes after ':'.
To stay with OpenFirmware spirit I would suggest to use the following
syntax for rom instances:
/rom at genroms/linuxboot.bin:rom2
/pci at i0cf8/scsi at 3:rom2

I can add support for such syntax to my patch too.

> Do you know what the magic qemu command-line options are to enable
> bootindex for roms, floppies, scsi, etc is?
You need latest qemu for that (not qemu-kvm):

qemu -drive file=/dev/null,if=none,id=d1,media=cdrom -device ide-drive,drive=d1,bootindex=0 \
-drive file=fedora.iso,if=none,id=d2,media=cdrom -device ide-drive,drive=d2,bootindex=110 \
-drive if=none,file=/tmp/a,id=fda \
-drive if=none,file=/tmp/a,id=fdb \
-global isa-fdc.bootindexB=30 \
-global isa-fdc.bootindexA=40 \
-global isa-fdc.driveA=fda \
-global isa-fdc.driveB=fdb \
-netdev type=user,id=net1 -device virtio-net-pci,netdev=net1,bootindex=20 \
-netdev type=user,id=net2 -device e1000,netdev=net2,bootindex=10 \
-drive file=rhel6.qcow2,if=none,id=d3 -device ide-drive,drive=d3,bus=ide.0,bootindex=100 \
-drive file=/dev/null,if=none,id=d4 -device virtio-blk-pci,drive=d4,bootindex=95 \
-boot menu=on

> 
> -Kevin
> 
> 
> diff --git a/src/boot.c b/src/boot.c
> index e83dcdc..836a8b2 100644
> --- a/src/boot.c
> +++ b/src/boot.c
> @@ -13,6 +13,7 @@
>  #include "boot.h" // func defs
>  #include "cmos.h" // inb_cmos
>  #include "paravirt.h" // romfile_loadfile
> +#include "pci.h" //pci_bdf_to_*
>  
>  
>  /****************************************************************
> @@ -29,7 +30,7 @@ loadBootOrder(void)
>      if (!f)
>          return;
>  
> -    int i;
> +    int i = 0;
>      BootorderCount = 1;
>      while (f[i]) {
>          if (f[i] == '\n')
> @@ -51,35 +52,122 @@ loadBootOrder(void)
>          if (f) {
>              *f = '\0';
>              f++;
> -            dprintf(3, "%d: %s\n", i, Bootorder[i]);
>              i++;
>          }
> +        dprintf(3, "%d: %s\n", i, Bootorder[i]);
>      } while(f);
>  }
>  
> -int bootprio_find_pci_device(int bdf)
> +// See if 'str' matches 'glob' - if glob contains an '*' character it
> +// will match any number of characters in str that aren't a '/' or the
> +// next glob character.
> +static char *
> +glob_prefix(const char *glob, const char *str)
>  {
> +    for (;;) {
> +        if (!*glob && (!*str || *str == '/'))
> +            return (char*)str;
> +        if (*glob == *str) {
> +            glob++;
> +            str++;
> +            continue;
> +        }
> +        if (*glob != '*')
> +            return NULL;
> +        if (*str && *str != '/' && *str != glob[1])
> +            str++;
> +        else
> +            glob++;
> +    }
> +}
> +
> +// Search the bootorder list for the given glob pattern.
> +static int
> +find_prio(const char *glob)
> +{
> +    int i;
> +    for (i = 0; i < BootorderCount; i++)
> +        if (glob_prefix(glob, Bootorder[i]))
> +            return i;
>      return -1;
>  }
>  
> +#define FW_PCI_DOMAIN "/pci at i0cf8"
> +
> +static char *
> +build_pci_path(char *buf, int max, int bdf)
> +{
> +    // Build a glob string for a bdf - for example: /pci at i0cf8/*@1,2
> +    char *p = buf;
> +    int bus = pci_bdf_to_bus(bdf);
> +    if (bus)
> +        // XXX - this isn't the correct path syntax
> +        p += snprintf(p, buf+max-p, "/bus%x", bus);
> +
> +    int dev = pci_bdf_to_dev(bdf), fn = pci_bdf_to_fn(bdf);
> +    if (!fn)
> +        snprintf(buf, buf+max-p, "%s/*@%x", FW_PCI_DOMAIN, dev);
> +    else
> +        snprintf(buf, buf+max-p, "%s/*@%x,%x", FW_PCI_DOMAIN, dev, fn);
> +    return buf;
> +}
> +
> +int bootprio_find_pci_device(int bdf)
> +{
> +    // Find pci device - for example: /pci at i0cf8/ethernet at 5
> +    char pci[256];
> +    return find_prio(build_pci_path(pci, sizeof(pci), bdf));
> +}
> +
>  int bootprio_find_ata_device(int bdf, int chanid, int slave)
>  {
> -    return -1;
> +    if (bdf == -1)
> +        // support only pci machine for now
> +        return -1;
> +    // Find ata drive - for example: /pci at i0cf8/ide at 1,1/drive at 1/disk at 0
> +    char pci[256], desc[256];
> +    snprintf(desc, sizeof(desc), "%s/drive@%x/disk@%x"
> +             , build_pci_path(pci, sizeof(pci), bdf), chanid, slave);
> +    return find_prio(desc);
>  }
>  
> -int bootprio_find_fdc_device(int bfd, int port, int fdid)
> +int bootprio_find_fdc_device(int bdf, int port, int fdid)
>  {
> -    return -1;
> +    if (bdf == -1)
> +        // support only pci machine for now
> +        return -1;
> +    // Find floppy - for example: /pci at i0cf8/isa at 1/fdc at 03f1/floppy at 0
> +    char pci[256], desc[256];
> +    snprintf(desc, sizeof(desc), "%s/fdc@%04x/floppy@%x"
> +             , build_pci_path(pci, sizeof(pci), bdf), port, fdid);
> +    return find_prio(desc);
>  }
>  
>  int bootprio_find_pci_rom(int bdf, int instance)
>  {
> -    return -1;
> +    // Find pci rom - for example: /pci at i0cf8/scsi at 3/rom2
> +    char pci[256], desc[256];
> +    build_pci_path(pci, sizeof(pci), bdf);
> +    if (instance)
> +        snprintf(desc, sizeof(desc), "%s/rom%x", pci, instance);
> +    else
> +        snprintf(desc, sizeof(desc), "%s/rom", pci);
> +    int prio = find_prio(desc);
> +    if (prio >= 0)
> +        return prio;
> +    // Didn't find rom string - try to match just the pci device.
> +    return find_prio(pci);
>  }
>  
>  int bootprio_find_named_rom(const char *name, int instance)
>  {
> -    return -1;
> +    // Find named rom - for example: /rom at genroms/linuxboot.bin
> +    char desc[256];
> +    if (instance)
> +        snprintf(desc, sizeof(desc), "/rom@%s", name);
> +    else
> +        snprintf(desc, sizeof(desc), "/rom%d@%s", instance, name);
> +    return find_prio(desc);
>  }
>  
>  

--
			Gleb.



More information about the SeaBIOS mailing list