/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:cindent:textwidth=0: * * Copyright (C) 2005 Dell Inc. * by Michael Brown * Licensed under the Open Software License version 2.1 * * Alternatively, you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. */ #define LIBSMBIOS_C_SOURCE #include "smbios_c/compat.h" #include #include "smbios_c/cmos.h" #include "smbios_c/memory.h" #include "smbios_c/smbios.h" #include "smbios_c/obj/token.h" #include "smbios_c/token.h" #include "smbios_c/system_info.h" #include "dell_magic.h" #include "sysinfo_impl.h" #define UP_ANCHOR "_UP_" #define UP_ANCHOR_LEN 4 #if defined(_MSC_VER) #pragma pack(push,1) #endif struct up_info { char anchor[4]; u16 stuff1; // anybody know what this is? u8 offset; u16 stuff2; // anybody know what this is? u8 flag; } LIBSMBIOS_C_PACKED_ATTR; #if defined(_MSC_VER) #pragma pack(pop) #endif __hidden bool get_up_offset_and_flag(struct up_info *up) { s64 offset = memory_search( UP_ANCHOR, UP_ANCHOR_LEN, 0xF0000UL, 0xFFFFFUL, 16); if (!offset) offset = memory_search( UP_ANCHOR, UP_ANCHOR_LEN, 0xF0000UL, 0xFFFFFUL, 1); if (offset!=0 && offset!=-1) { int ret; ret = memory_read(up, (u64)offset, sizeof(*up)); if (ret < 0) return false; } fnprintf("offset 0x%llx", offset); return (offset!=0 && offset!=-1); } __hidden int up_boot_helper(int flag) { // flag:0 == get // flag:1 == set true // flag:2 == set false // retval = -1: error trying to perform function // retval = 0: NO BOOT TO UP CAPABILITY // retval = 1 && set; set to value // retval = 2 && !set; UP not active // retval = 3 && !set; UP Active int retval = 0; struct up_info up; memset(&up, 0, sizeof(up)); bool found = get_up_offset_and_flag(&up); if(!found) goto out; // instantiate token table to set up checksum observers token_table_factory(TOKEN_DEFAULTS); // find 0xD4 token struct smbios_struct *s = smbios_get_next_struct_by_type(0, 0xD4); if(!s) goto out_err; // copy index/data port struct indexed_io_access_structure *d4 = 0; d4 = (struct indexed_io_access_structure *)s; u32 indexPort = d4->indexPort; u32 dataPort = d4->dataPort; // read byte u8 byte; int ret = cmos_read_byte(&byte, indexPort, dataPort, up.offset); if (ret<0) goto out_err; fnprintf("up offset: 0x%04x\n", up.offset); fnprintf("up flag : 0x%04x\n", up.flag); fnprintf("read byte: 0x%04x\n", byte); if(flag==0) { if( (byte & up.flag) == up.flag ) retval = 3; if( (byte & up.flag) != up.flag ) retval = 2; } else { byte |= up.flag; if(flag==2) byte &= ~up.flag; ret = cmos_write_byte(byte, indexPort, dataPort, up.offset); if (ret<0) goto out_err; retval = 1; } goto out; out_err: retval = -1; goto out; out: return retval; } LIBSMBIOS_C_DLL_SPEC int sysinfo_has_up_boot_flag() { return up_boot_helper(0); } LIBSMBIOS_C_DLL_SPEC int sysinfo_get_up_boot_flag() { return up_boot_helper(0) - 2; } LIBSMBIOS_C_DLL_SPEC int sysinfo_set_up_boot_flag(int state) { return up_boot_helper( state==1? 1:2 ); }