Как установить insync в void linux?

Мне удалось успешно запустить Windows 10 с помощью приведенного ниже кода. Он обрабатывает обе неисправности, которые могут быть у вентилятора: :«вентилятор внезапно останавливается с режимом работы вентилятора = 0» и «вентилятор внезапно останавливается со скоростью вращения > 10000 с электрическим шумом, исходящим от вентилятора». Для этого требуется программа, загружающая Winring0, например ThrottleStop, работающая в фоновом режиме. Я не тестировал его с установленным Clevo Control Center. Компилируется с MinGW -w64 с\yourmingwpath\i686-w64-mingw32-gcc.exe \yoursourcepath\main.c -o \yourexepath\main.exe -Wall -mwindows

#define UNICODE 1
#define _UNICODE 1

#include 
#include 
#include 
#include 

#define OLS_TYPE 40000
#define IOCTL_OLS_READ_IO_PORT_BYTE CTL_CODE(OLS_TYPE, 0x833, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_OLS_WRITE_IO_PORT_BYTE CTL_CODE(OLS_TYPE, 0x836, METHOD_BUFFERED, FILE_WRITE_ACCESS)

#define EC_SC 0x66
#define EC_DATA 0x62

#define IBF 1
#define OBF 0
#define EC_SC_READ_CMD 0x80

typedef struct _OLS_WRITE_IO_PORT_INPUT {
    ULONG   PortNumber; 
    union {
        ULONG   LongData;
        USHORT  ShortData;
        UCHAR   CharData;
    };
}   OLS_WRITE_IO_PORT_INPUT;

HANDLE hDevice = INVALID_HANDLE_VALUE;
char filename[1024] = {0};

WORD WInp(WORD port) {
    FILE *outlog;
    unsigned int error = 0;

    DWORD   returnedLength = 0;
    WORD    value = 0;
    BOOL    bResult = FALSE;
    bResult = DeviceIoControl(hDevice,
                            IOCTL_OLS_READ_IO_PORT_BYTE,
                            &port, sizeof(port),
                            &value, sizeof(value),
                            &returnedLength,
                            NULL );
    if (bResult) {
        /*outlog = fopen(filename, "ab");
        fprintf(outlog, "port=%d, value=%d, retlength=%d\n", port, value, (int)returnedLength);
        fclose(outlog);*/
        return value;
    } else {
        error = GetLastError();
        outlog = fopen(filename, "ab");
        fprintf(outlog, "DeviceIoControl (read) failed. Error %d.\n", error);
        fclose(outlog);
        CloseHandle(hDevice);
        return 0;
    }
}

WORD WOutp(WORD port, BYTE value) {
    FILE *outlog;
    unsigned int error = 0;

    DWORD   returnedLength = 0;
    BOOL    bResult = FALSE;
    DWORD   length = 0;
    OLS_WRITE_IO_PORT_INPUT inBuf;
    inBuf.CharData = value;
    inBuf.PortNumber = port;
    length = offsetof(OLS_WRITE_IO_PORT_INPUT, CharData) + sizeof(inBuf.CharData);
    bResult = DeviceIoControl(hDevice,
                            IOCTL_OLS_WRITE_IO_PORT_BYTE,
                            &inBuf, length,
                            NULL, 0,
                            &returnedLength,
                            NULL);
    if (bResult) {
        /*outlog = fopen(filename, "ab");
        fprintf(outlog, "port=%d, value=%d, retlength=%d\n", port, value, (int)returnedLength);
        fclose(outlog);*/
        return value;
    } else {
        error = GetLastError();
        outlog = fopen(filename, "ab");
        fprintf(outlog, "DeviceIoControl (write) failed. Error %d.\n", error);
        fclose(outlog);
        CloseHandle(hDevice);
        return 0;
    }
}

int wait_ec(const unsigned int port, const unsigned int flag, const char value) {
    int i = 0;
    unsigned char data = WInp(port);

    while (((data >> flag)&0x1)!=value) {
        Sleep(1);
        if (i>10) {
            //printf( "Still waiting on port 0x%x, data=0x%x, flag=0x%x, value=0x%x, i=%d\n", port, data, flag, value, i);
            return 0;
        }
        i++;
        data = WInp(port);
    }
    //printf( "Succeeded port 0x%x, data=0x%x, flag=0x%x, value=0x%x, i=%d\n", port, data, flag, value, i);
    return 0;
}

unsigned char read_ec(const unsigned int port) {
    wait_ec(EC_SC, IBF, 0);
    WOutp(EC_SC, EC_SC_READ_CMD);
    wait_ec(EC_SC, IBF, 0);
    WOutp(EC_DATA, port);
    wait_ec(EC_SC, OBF, 1);
    return WInp(EC_DATA);
}

void do_ec(const unsigned int cmd, const unsigned int port, const unsigned char value) {
    wait_ec(EC_SC, IBF, 0);
    WOutp(EC_SC, cmd);
    wait_ec(EC_SC, IBF, 0);
    WOutp(EC_DATA, port);
    wait_ec(EC_SC, IBF, 0);
    WOutp(EC_DATA, value);
    wait_ec(EC_SC, IBF, 0);
    return;
}

void write_fan_duty(int duty_percentage) {
    do_ec(0x99, 0x01, (int)(((double) duty_percentage) / 100.0 * 255.0));
    //FILE *outlog = fopen(filename, "ab");
    //fprintf(outlog, "Fan set to %d\n", duty_percentage);
    //fclose(outlog);
    return;
}

int main(){
    // get the path of this executable and append "stdout.txt\0" to it for the log file.
    int i = GetModuleFileNameA(NULL, filename, 1024);
    for (;i>0 && filename[i] != '\\';i--) {}
    char *dest=&filename[i+1], *src="stdout.txt\0";
    for (i=0;i<11;i++) dest[i]=src[i];

    FILE *outlog;
    outlog = fopen(filename, "wb"); // clear the log at every start
    fclose(outlog);
    unsigned int error = 0;

    // I could loop CreateFile until a valid handle is returned (which means that WinRing0_1_2_0 got started by throttlestop)
    // but windows defender blocks the program at start for a few seconds with 100% core usage if i do that.

    Sleep(3000); //... so this is what i have to do instead. Disgusting.

    hDevice = CreateFile(L"\\\\.\\WinRing0_1_2_0",
                        GENERIC_READ | GENERIC_WRITE,
                        0,
                        NULL,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);

    if (hDevice == INVALID_HANDLE_VALUE) {
        error = GetLastError();
        if (error == ERROR_ACCESS_DENIED) {
            outlog = fopen(filename, "ab");
            fprintf(outlog, "CreateFile failed. Please retry as administrator.\n");
            fclose(outlog);
        } else if (error == ERROR_FILE_NOT_FOUND) {
            outlog = fopen(filename, "ab");
            fprintf(outlog, "CreateFile failed. The WinRing0 driver is probably not loaded yet.\n");
            fclose(outlog);
        } else {
            outlog = fopen(filename, "ab");
            fprintf(outlog, "CreateFile failed. Error %d.\n", error);
            fclose(outlog);
        }
        return 0;
    }

    int val_duty, raw_rpm, val_rpm, temp, last_valid_duty=50;
    while (1) {
        val_duty = (int) ((double) (read_ec(0xCE)) / 255.0 * 100.0);
        raw_rpm = (read_ec(0xD0) << 8) + (read_ec(0xD1));
        if (raw_rpm == 0)
            val_rpm = 0;
        else
            val_rpm = 2156220 / raw_rpm;
        temp = read_ec(0x07);

        //outlog = fopen(filename, "ab");
        //fprintf(outlog, "FAN Duty: %d%%, FAN RPMs: %d RPM, CPU Temp: %d°C\n", val_duty, val_rpm, temp);
        //fclose(outlog);

        if (val_rpm > 10000 || val_duty == 0) {
            // there are two malfunctions that can happen:
            // - fan stops suddenly with fan duty=0
            // - fan stops suddenly with rpm > 10000 with a electric noise that can be heard coming from the fan.
            outlog = fopen(filename, "ab");
            fprintf(outlog, "MALFUNCTION DETECTED: val_rpm=%d, val_duty=%d\n", val_rpm, val_duty);
            fclose(outlog);
            // Panic :O
            if (last_valid_duty<80) {
                write_fan_duty(last_valid_duty+20);
            } else {
                write_fan_duty(last_valid_duty-20);
            }
        } else {
            // This is the custom fan curve code. Can be adjusted to your liking.
            // It's required because i don't know to to set the fan back to "automatic" without manual intervention.
            // Can definitely conflict with other fan speed programs, so be careful.
            // Writes to fan speed are limited to only if the target fan duty changes.
            if (temp<55) {
                if (last_valid_duty > 32 || last_valid_duty < 29) write_fan_duty(31);
            } else if (temp<60) {
                if (last_valid_duty > 42 || last_valid_duty < 39) write_fan_duty(41);
            } else if (temp<65) {
                if (last_valid_duty > 52 || last_valid_duty < 49) write_fan_duty(51);
            } else if (temp<70) {
                if (last_valid_duty > 62 || last_valid_duty < 59) write_fan_duty(61);
            } else if (temp<75) {
                if (last_valid_duty > 72 || last_valid_duty < 69) write_fan_duty(71);
            } else if (temp<80) {
                if (last_valid_duty > 82 || last_valid_duty < 79) write_fan_duty(81);
            } else if (temp<85) {
                if (last_valid_duty > 92 || last_valid_duty < 89) write_fan_duty(91);
            } else {
                if (last_valid_duty < 98) write_fan_duty(100);
            }
            last_valid_duty = val_duty;
        }
        Sleep(200);
    }
    return 0;
}

Я не портировал код для использования в ОС на базе Linux -. Для этого потребуется:

  • замена функций WInp(port)и WOutp(port, value)на inb(port)и outb(value, port),
  • добавление iopermв начале, например в этом фрагменте кода ,
  • замена Sleep(milliseconds)на usleep(microseconds),
  • очистка всех теперь бесполезных включений, определений, структур и дескрипторов,
  • замена GetModuleFileNameAэквивалентной функцией.

0
10.02.2021, 01:07
1 ответ

Мне удалось преобразовать пакет deb в локальный пакет, который можно установить в void linux с помощью скрипта xdebhttps://github.com/toluschr/xdeb.

Было легко преобразовать и установить с помощью сценария xdeb.

0
18.03.2021, 22:31

Теги

Похожие вопросы