If open-dev is called on a raw block device such as cdrom, the current code will always attempt to interpose a partition handler for the first valid partition table type it finds.
This is incorrect when opening a raw block device directly as it means we "fall into" the first valid partition that can be found, rather than using the full raw device. Fix this by only attempting to interpose a partition handler if the package arguments are not empty.
This fixes the NetBSD SPARC64 bootloader as reported by Martin Husemann in https://bugs.launchpad.net/qemu/+bug/1169856.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/packages/disk-label.c | 105 ++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 49 deletions(-)
diff --git a/openbios-devel/packages/disk-label.c b/openbios-devel/packages/disk-label.c index 44b9f9e..1c18d74 100644 --- a/openbios-devel/packages/disk-label.c +++ b/openbios-devel/packages/disk-label.c @@ -73,63 +73,70 @@ dlabel_open( dlabel_info_t *di ) di->filesystem_ph = 0; di->parent_seek_xt = find_parent_method("seek"); di->parent_tell_xt = find_parent_method("tell"); - di->parent_read_xt = find_parent_method("read"); + di->parent_read_xt = find_parent_method("read");
- /* Read first block from parent device */ - DPUSH(0); - call_package(di->parent_seek_xt, my_parent()); - POP(); - - PUSH(pointer2cell(block0)); - PUSH(sizeof(block0)); - call_package(di->parent_read_xt, my_parent()); - status = POP(); - if (status != sizeof(block0)) - goto out; - - /* Find partition handler */ - PUSH( pointer2cell(block0) ); - selfword("find-part-handler"); - ph = POP_ph(); - if( ph ) { - /* We found a suitable partition handler, so interpose it */ - DPRINTF("Partition found on disk - scheduling interpose with ph " FMT_ucellx "\n", ph); - - push_str(path); - PUSH_ph(ph); - fword("interpose"); + /* If arguments have been passed, determine the partition/filesystem type */ + if (path && strlen(path)) {
- success = 1; - } else { - /* unknown (or missing) partition map, - * try the whole disk - */ + /* Read first block from parent device */ + DPUSH(0); + call_package(di->parent_seek_xt, my_parent()); + POP();
- DPRINTF("Unknown or missing partition map; trying whole disk\n"); + PUSH(pointer2cell(block0)); + PUSH(sizeof(block0)); + call_package(di->parent_read_xt, my_parent()); + status = POP(); + if (status != sizeof(block0)) + goto out;
- /* Probe for filesystem from start of device */ - DPUSH ( 0 ); - PUSH_ih( my_self() ); - selfword("find-filesystem"); + /* Find partition handler */ + PUSH( pointer2cell(block0) ); + selfword("find-part-handler"); ph = POP_ph(); if( ph ) { - /* If we have been asked to open a particular file, interpose the filesystem package with the passed filename as an argument */ - di->filesystem_ph = ph; - - DPRINTF("Located filesystem with ph " FMT_ucellx "\n", ph); - DPRINTF("path: %s length: %d\n", path, strlen(path)); - - if (path && strlen(path)) { - DPRINTF("INTERPOSE!\n"); - - push_str( path ); - PUSH_ph( ph ); - fword("interpose"); + /* We found a suitable partition handler, so interpose it */ + DPRINTF("Partition found on disk - scheduling interpose with ph " FMT_ucellx "\n", ph); + + push_str(path); + PUSH_ph(ph); + fword("interpose"); + + success = 1; + } else { + /* unknown (or missing) partition map, + * try the whole disk + */ + + DPRINTF("Unknown or missing partition map; trying whole disk\n"); + + /* Probe for filesystem from start of device */ + DPUSH ( 0 ); + PUSH_ih( my_self() ); + selfword("find-filesystem"); + ph = POP_ph(); + if( ph ) { + /* If we have been asked to open a particular file, interpose the filesystem package with the passed filename as an argument */ + di->filesystem_ph = ph; + + DPRINTF("Located filesystem with ph " FMT_ucellx "\n", ph); + DPRINTF("path: %s length: %d\n", path, strlen(path)); + + if (path && strlen(path)) { + DPRINTF("INTERPOSE!\n"); + + push_str( path ); + PUSH_ph( ph ); + fword("interpose"); + } + } else if (path && strcmp(path, "%BOOT") != 0) { + goto out; } - } else if (path && strcmp(path, "%BOOT") != 0) { - goto out; - }
+ success = 1; + } + } else { + /* No arguments we passed, so we just use the parent raw device directly */ success = 1; }