From patchwork Tue Nov 30 14:01:00 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gleb Natapov X-Patchwork-Id: 366931 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oAUE1YKq031872 for ; Tue, 30 Nov 2010 14:01:35 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752655Ab0K3OBb (ORCPT ); Tue, 30 Nov 2010 09:01:31 -0500 Received: from mx1.redhat.com ([209.132.183.28]:43834 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751931Ab0K3OBa (ORCPT ); Tue, 30 Nov 2010 09:01:30 -0500 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oAUE1255014991 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 30 Nov 2010 09:01:02 -0500 Received: from dhcp-1-237.tlv.redhat.com (dhcp-1-237.tlv.redhat.com [10.35.1.237]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id oAUE110i029199; Tue, 30 Nov 2010 09:01:01 -0500 Received: by dhcp-1-237.tlv.redhat.com (Postfix, from userid 13519) id 98ECD133F76; Tue, 30 Nov 2010 16:01:00 +0200 (IST) Date: Tue, 30 Nov 2010 16:01:00 +0200 From: Gleb Natapov To: "Kevin O'Connor" Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org, seabios@seabios.org Subject: Re: [PATCHv6 00/16] boot order specification Message-ID: <20101130140100.GH2187@redhat.com> References: <20101127170619.GB14385@redhat.com> <20101127174726.GA15238@morn.localdomain> <20101127181541.GC14385@redhat.com> <20101127184012.GA17455@morn.localdomain> <20101127190424.GD14385@redhat.com> <20101127210744.GA21727@morn.localdomain> <20101128074534.GE6897@redhat.com> <20101128171543.GA21987@morn.localdomain> <20101128184734.GE14385@redhat.com> <20101130013402.GB3488@morn.localdomain> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20101130013402.GB3488@morn.localdomain> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Tue, 30 Nov 2010 14:01:35 +0000 (UTC) diff --git a/src/boot.c b/src/boot.c index 021b8ac..c1ac9af 100644 --- a/src/boot.c +++ b/src/boot.c @@ -67,6 +67,47 @@ boot_setup(void) if (!(inb_cmos(CMOS_BIOS_BOOTFLAG1) & 1)) IPL.checkfloppysig = 1; } + + u32 file = romfile_find("bootorder"); + if (!file) + return; + + int filesize = romfile_size(file); + char *f = malloc_tmphigh(filesize); + dprintf(3, "bootorder file found (len %d)\n", filesize); + + if (!f) { + dprintf(1, "can't allocate memory for bootorder file\n"); + return; + } + + romfile_copy(file, f, filesize); + int i; + IPL.fw_bootorder_count = 1; + while(f[i]) { + if (f[i] == '\n') + IPL.fw_bootorder_count++; + i++; + } + IPL.fw_bootorder = malloc_tmphigh(IPL.fw_bootorder_count*sizeof(char*)); + if (!IPL.fw_bootorder) { + dprintf(1, "can't allocate memory for bootorder\n"); + free(f); + return; + } + + dprintf(3, "boot order:\n"); + i = 0; + do { + IPL.fw_bootorder[i] = f; + f = strchr(f, '\n'); + if (*f) { + *f = '\0'; + f++; + dprintf(3, "%d: %s\n", i, IPL.fw_bootorder[i]); + i++; + } + } while(f); } // Add a BEV vector for a given pnp compatible option rom. @@ -506,3 +547,78 @@ handle_19(void) SET_EBDA(boot_sequence, 0); do_boot(0); } + +/* + * function returns string representing firts device path element in 'dp' + * and puts pointer to the reset of the device path into 'end' + */ +static char *dev_path_get_node(const char *dp, const char **end) +{ + int len; + char *node; + + dp += 1; /* skip '/' */ + + *end = strchr(dp, '/'); + + if (*end == NULL) { + len = strlen(dp); /* last path element */ + *end = dp + len; + } + else + len = *end - dp; + + if (len == 0) + return NULL; + + node = malloc_tmphigh(len + 1); + memcpy(node, dp, len); + node[len] = '\0'; + + return node; +} + +static int match_unit_address(const char *pe, const char *unit_address) +{ + char *s = strchr(pe, '@'); + + if (s == NULL) + return 0; + + return !strcmp(s, unit_address); +} + +#define FW_PCI_DOMAIN "/pci@i0cf8" + +int bootprio_match_pci_device(int dev, int fn) +{ + int i, l; + char pci[7]; + + if (!fn) + l = snprintf(pci, sizeof(pci), "@%x", dev); + else + l = snprintf(pci, sizeof(pci), "@%x,%x", dev, fn); + + for (i = 0; i < IPL.fw_bootorder_count; i++) { + char *node; + const char *next, *path = IPL.fw_bootorder[i]; + int r; + + /* is pci domain? */ + if (memcmp(path, FW_PCI_DOMAIN, strlen(FW_PCI_DOMAIN))) + continue; + + node = dev_path_get_node(path + strlen(FW_PCI_DOMAIN), &next); + if (node == NULL) + continue; + + r = match_unit_address(node, pci); + + free(node); + if (r) + return i; + } + + return -1; +} diff --git a/src/boot.h b/src/boot.h index db046e3..07467e6 100644 --- a/src/boot.h +++ b/src/boot.h @@ -20,6 +20,8 @@ struct ipl_s { int bevcount, bcvcount; u32 bootorder; int checkfloppysig; + char **fw_bootorder; + int fw_bootorder_count; }; #define IPL_TYPE_FLOPPY 0x01 @@ -44,5 +46,6 @@ void add_bcv(u16 seg, u16 ip, u16 desc); struct drive_s; void add_bcv_internal(struct drive_s *drive_g); void boot_prep(void); +int bootprio_match_pci_device(int dev, int fn); #endif // __BOOT_H diff --git a/src/optionroms.c b/src/optionroms.c index 854c33f..5500c56 100644 --- a/src/optionroms.c +++ b/src/optionroms.c @@ -74,6 +74,13 @@ struct pnp_data { // The end of the last deployed rom. u32 RomEnd = BUILD_ROM_START; +static struct rom_boot_prio { + u32 addr; + int prio; +} rom2prio[92]; + +static int rom2prio_index; + /**************************************************************** * Helper functions @@ -342,7 +349,20 @@ init_pcirom(u16 bdf, int isvga) if (! rom) // No ROM present. return -1; - return init_optionrom(rom, bdf, isvga); + + int r = init_optionrom(rom, bdf, isvga); + + if (r || !is_valid_rom(rom)) + return r; + + rom2prio[rom2prio_index].addr = (u32)rom; + rom2prio[rom2prio_index].prio = + bootprio_match_pci_device(pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)); + dprintf(3, "pci rom at memory address %x has boot prio %d\n", + rom2prio[rom2prio_index].addr, rom2prio[rom2prio_index].prio); + rom2prio_index++; + + return r; } diff --git a/src/util.c b/src/util.c index 8e02d1e..cfb4add 100644 --- a/src/util.c +++ b/src/util.c @@ -253,6 +253,17 @@ strtcpy(char *dest, const char *src, size_t len) return dest; } +// locate first occurance of character c in the string s +char * +strchr(const char *s, int c) +{ + int i = 0; + + while(s[i] && s[i] != c) + i++; + + return s[i] ? (char*)&s[i] : NULL; +} /**************************************************************** * Keyboard calls diff --git a/src/util.h b/src/util.h index 18ab814..cd46d9c 100644 --- a/src/util.h +++ b/src/util.h @@ -208,6 +208,7 @@ void *memcpy(void *d1, const void *s1, size_t len); void iomemcpy(void *d, const void *s, u32 len); void *memmove(void *d, const void *s, size_t len); char *strtcpy(char *dest, const char *src, size_t len); +char *strchr(const char *s, int c); int get_keystroke(int msec); // stacks.c