1 /* 2 * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2015, 2019 SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #include "libodm_aix.hpp" 27 #include "misc_aix.hpp" 28 #include <stdlib.h> 29 #include <dlfcn.h> 30 #include <string.h> 31 #include "runtime/arguments.hpp" 32 33 34 dynamicOdm::dynamicOdm() { 35 const char *libodmname = "/usr/lib/libodm.a(shr_64.o)"; 36 _libhandle = dlopen(libodmname, RTLD_MEMBER | RTLD_NOW); 37 if (!_libhandle) { 38 trcVerbose("Couldn't open %s", libodmname); 39 return; 40 } 41 _odm_initialize = (fun_odm_initialize )dlsym(_libhandle, "odm_initialize" ); 42 _odm_set_path = (fun_odm_set_path )dlsym(_libhandle, "odm_set_path" ); 43 _odm_mount_class = (fun_odm_mount_class)dlsym(_libhandle, "odm_mount_class"); 44 _odm_get_obj = (fun_odm_get_obj )dlsym(_libhandle, "odm_get_obj" ); 45 _odm_terminate = (fun_odm_terminate )dlsym(_libhandle, "odm_terminate" ); 46 if (!_odm_initialize || !_odm_set_path || !_odm_mount_class || !_odm_get_obj || !_odm_terminate) { 47 trcVerbose("Couldn't find all required odm symbols from %s", libodmname); 48 dlclose(_libhandle); 49 _libhandle = NULL; 50 return; 51 } 52 } 53 54 dynamicOdm::~dynamicOdm() { 55 if (_libhandle) { dlclose(_libhandle); } 56 } 57 58 59 void odmWrapper::clean_data() { if (_data) { free(_data); _data = NULL; } } 60 61 62 int odmWrapper::class_offset(const char *field, bool is_aix_5) 63 { 64 assert(has_class(), "initialization"); 65 for (int i = 0; i < odm_class()->nelem; i++) { 66 if (strcmp(odm_class()->elem[i].elemname, field) == 0) { 67 int offset = odm_class()->elem[i].offset; 68 if (is_aix_5) { offset += LINK_VAL_OFFSET; } 69 return offset; 70 } 71 } 72 return -1; 73 } 74 75 76 void odmWrapper::determine_os_kernel_version(uint32_t* p_ver) { 77 int major_aix_version = ((*p_ver) >> 24) & 0xFF, 78 minor_aix_version = ((*p_ver) >> 16) & 0xFF; 79 assert(*p_ver, "must be initialized"); 80 81 odmWrapper odm("product", "/usr/lib/objrepos"); // could also use "lpp" 82 if (!odm.has_class()) { 83 trcVerbose("try_determine_os_kernel_version: odm init problem"); 84 return; 85 } 86 int voff, roff, moff, foff; 87 bool is_aix_5 = (major_aix_version == 5); 88 voff = odm.class_offset("ver", is_aix_5); 89 roff = odm.class_offset("rel", is_aix_5); 90 moff = odm.class_offset("mod", is_aix_5); 91 foff = odm.class_offset("fix", is_aix_5); 92 if (voff == -1 || roff == -1 || moff == -1 || foff == -1) { 93 trcVerbose("try_determine_os_kernel_version: could not get offsets"); 94 return; 95 } 96 if (!odm.retrieve_obj("name='bos.mp64'")) { 97 trcVerbose("try_determine_os_kernel_version: odm_get_obj failed"); 98 return; 99 } 100 int version, release, modification, fix_level; 101 do { 102 version = odm.read_short(voff); 103 release = odm.read_short(roff); 104 modification = odm.read_short(moff); 105 fix_level = odm.read_short(foff); 106 trcVerbose("odm found version: %d.%d.%d.%d", version, release, modification, fix_level); 107 if (version >> 8 != 0 || release >> 8 != 0 || modification >> 8 != 0 || fix_level >> 8 != 0) { 108 trcVerbose("8 bit numbers expected"); 109 return; 110 } 111 } while (odm.retrieve_obj()); 112 113 if (version != major_aix_version || release != minor_aix_version) { 114 trcVerbose("version determined by odm does not match uname"); 115 return; 116 } 117 *p_ver = version << 24 | release << 16 | modification << 8 | fix_level; 118 }