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