1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251875Speter * contributor license agreements. See the NOTICE file distributed with 3251875Speter * this work for additional information regarding copyright ownership. 4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251875Speter * (the "License"); you may not use this file except in compliance with 6251875Speter * the License. You may obtain a copy of the License at 7251875Speter * 8251875Speter * http://www.apache.org/licenses/LICENSE-2.0 9251875Speter * 10251875Speter * Unless required by applicable law or agreed to in writing, software 11251875Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251875Speter * See the License for the specific language governing permissions and 14251875Speter * limitations under the License. 15251875Speter */ 16251875Speter 17251875Speter/* The high resolution timer API provides access to the hardware timer 18251875Speter * running at around 1.1MHz. The amount this changes in a time slice is 19251875Speter * varies randomly due to system events, hardware interrupts etc 20251875Speter */ 21251875Speterstatic UCHAR randbyte_hrtimer() 22251875Speter{ 23251875Speter QWORD t1, t2; 24251875Speter UCHAR byte; 25251875Speter 26251875Speter DosTmrQueryTime(&t1); 27251875Speter DosSleep(5); 28251875Speter DosTmrQueryTime(&t2); 29251875Speter 30251875Speter byte = (t2.ulLo - t1.ulLo) & 0xFF; 31251875Speter byte ^= (t2.ulLo - t1.ulLo) >> 8; 32251875Speter return byte; 33251875Speter} 34251875Speter 35251875Speter 36251875Speter 37251875Speter/* A bunch of system information like memory & process stats. 38251875Speter * Not highly random but every bit helps.... 39251875Speter */ 40251875Speterstatic UCHAR randbyte_sysinfo() 41251875Speter{ 42251875Speter UCHAR byte = 0; 43251875Speter UCHAR SysVars[100]; 44251875Speter int b; 45251875Speter 46251875Speter DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars)); 47251875Speter 48251875Speter for (b = 0; b < 100; b++) { 49251875Speter byte ^= SysVars[b]; 50251875Speter } 51251875Speter 52251875Speter return byte; 53251875Speter} 54251875Speter 55251875Speter 56251875Speter 57251875Speter/* Similar in concept to randbyte_hrtimer() but accesses the CPU's internal 58251875Speter * counters which run at the CPU's MHz speed. We get separate 59251875Speter * idle / busy / interrupt cycle counts which should provide very good 60251875Speter * randomness due to interference of hardware events. 61251875Speter * This only works on newer CPUs (at least PPro or K6) and newer OS/2 versions 62251875Speter * which is why it's run-time linked. 63251875Speter */ 64251875Speter 65251875Speterstatic APIRET APIENTRY(*DosPerfSysCall) (ULONG ulCommand, ULONG ulParm1, 66251875Speter ULONG ulParm2, ULONG ulParm3) = NULL; 67251875Speterstatic HMODULE hDoscalls = 0; 68251875Speter#define CMD_KI_RDCNT (0x63) 69251875Speter 70251875Spetertypedef struct _CPUUTIL { 71251875Speter ULONG ulTimeLow; /* Low 32 bits of time stamp */ 72251875Speter ULONG ulTimeHigh; /* High 32 bits of time stamp */ 73251875Speter ULONG ulIdleLow; /* Low 32 bits of idle time */ 74251875Speter ULONG ulIdleHigh; /* High 32 bits of idle time */ 75251875Speter ULONG ulBusyLow; /* Low 32 bits of busy time */ 76251875Speter ULONG ulBusyHigh; /* High 32 bits of busy time */ 77251875Speter ULONG ulIntrLow; /* Low 32 bits of interrupt time */ 78251875Speter ULONG ulIntrHigh; /* High 32 bits of interrupt time */ 79251875Speter} CPUUTIL; 80251875Speter 81251875Speter 82251875Speterstatic UCHAR randbyte_perf() 83251875Speter{ 84251875Speter UCHAR byte = 0; 85251875Speter CPUUTIL util; 86251875Speter int c; 87251875Speter 88251875Speter if (hDoscalls == 0) { 89251875Speter char failed_module[20]; 90251875Speter ULONG rc; 91251875Speter 92251875Speter rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS", 93251875Speter &hDoscalls); 94251875Speter 95251875Speter if (rc == 0) { 96251875Speter rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&DosPerfSysCall); 97251875Speter 98251875Speter if (rc) { 99251875Speter DosPerfSysCall = NULL; 100251875Speter } 101251875Speter } 102251875Speter } 103251875Speter 104251875Speter if (DosPerfSysCall) { 105251875Speter if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) { 106251875Speter for (c = 0; c < sizeof(util); c++) { 107251875Speter byte ^= ((UCHAR *)&util)[c]; 108251875Speter } 109251875Speter } 110251875Speter else { 111251875Speter DosPerfSysCall = NULL; 112251875Speter } 113251875Speter } 114251875Speter 115251875Speter return byte; 116251875Speter} 117251875Speter 118251875Speter 119251875Speter 120251875Speterstatic UCHAR randbyte() 121251875Speter{ 122251875Speter return randbyte_hrtimer() ^ randbyte_sysinfo() ^ randbyte_perf(); 123251875Speter} 124