1 /* 2 * Copyright (C) 2007 Michael Brown <mbrown (at) fensystems.co.uk>. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19 FILE_LICENCE ( GPL2_OR_LATER ); 20 21 #include <stdint.h> 22 #include <string.h> 23 #include <errno.h> 24 #include <assert.h> 25 #include <gpxe/uaccess.h> 26 #include <gpxe/smbios.h> 27 #include <realmode.h> 28 #include <pnpbios.h> 29 30 /** @file 31 * 32 * System Management BIOS 33 * 34 */ 35 36 /** 37 * Find SMBIOS 38 * 39 * @v smbios SMBIOS entry point descriptor structure to fill in 40 * @ret rc Return status code 41 */ 42 static int bios_find_smbios ( struct smbios *smbios ) { 43 union { 44 struct smbios_entry entry; 45 uint8_t bytes[256]; /* 256 is maximum length possible */ 46 } u; 47 static unsigned int offset = 0; 48 size_t len; 49 unsigned int i; 50 uint8_t sum; 51 52 /* Try to find SMBIOS */ 53 for ( ; offset < 0x10000 ; offset += 0x10 ) { 54 55 /* Read start of header and verify signature */ 56 copy_from_real ( &u.entry, BIOS_SEG, offset, 57 sizeof ( u.entry )); 58 if ( u.entry.signature != SMBIOS_SIGNATURE ) 59 continue; 60 61 /* Read whole header and verify checksum */ 62 len = u.entry.len; 63 copy_from_real ( &u.bytes, BIOS_SEG, offset, len ); 64 for ( i = 0 , sum = 0 ; i < len ; i++ ) { 65 sum += u.bytes[i]; 66 } 67 if ( sum != 0 ) { 68 DBG ( "SMBIOS at %04x:%04x has bad checksum %02x\n", 69 BIOS_SEG, offset, sum ); 70 continue; 71 } 72 73 /* Fill result structure */ 74 DBG ( "Found SMBIOS v%d.%d entry point at %04x:%04x\n", 75 u.entry.major, u.entry.minor, BIOS_SEG, offset ); 76 smbios->address = phys_to_user ( u.entry.smbios_address ); 77 smbios->len = u.entry.smbios_len; 78 smbios->count = u.entry.smbios_count; 79 return 0; 80 } 81 82 DBG ( "No SMBIOS found\n" ); 83 return -ENODEV; 84 } 85 86 PROVIDE_SMBIOS ( pcbios, find_smbios, bios_find_smbios ); 87