开机splash上有彩条的时候使用
需要等到设备完全进系统后再执行
C#写的首个练手项目

/* NB30 AtCmdXSoftUpdate v0.1
   (C)Yuu 2020
 */
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO.Ports;

namespace AtCmdXSoftUpdate {
  class Program {
    static void Main(string[] args) {
        Console.WriteLine("Nb30 AtCmdXSoftUpdate v0.1");
      SerialPort serialPort = new SerialPort();
      serialPort.PortName = "COM30";
      serialPort.BaudRate = 115200;
      serialPort.DataBits = 8;
      serialPort.Parity = Parity.None;
      serialPort.StopBits = StopBits.One;
      serialPort.Handshake = Handshake.None;
      serialPort.ReadTimeout = 500;
      serialPort.WriteTimeout = 500;
      serialPort.Open();

      serialPort.WriteLine("AT+XSOFTUPDATE");
      Thread.Sleep(1000);
      string response = serialPort.ReadExisting();
      if (true == response.Contains("OK")) {
        Console.WriteLine("OK.Please wait device reboot!");
      } else {
        Console.WriteLine("ERROR");
      } 
      serialPort.Close();
    }
  }
}

日系机圈子里的,看到这个标题就应该明白这是干什么用的了吧?
说实话写的很烂,能凑合用的水平,也不知道那么多依赖的更新之后,还能不能用。
稍稍做了一些小修补,由于在国外也没有机器测试,还是希望有人可以来测一下。
这个小东西是很久以前的商用品了,现在也觉得没啥价值,故直接公开
想法及思路来自tewilove
依赖PyUSB

# NB30 SHDIAG USB Protocol v0.2
# (C)Yuu 2019
# Modified History:
# Nov.02-2022:v0.2:Normal Improvement

import sys
import usb.core
import usb.util
import random

NB30_USB_VID = 0x04dd
NB30_USB_PID = 0x933a


def shdiag_xchar(c):
    xft = [0, 2, 4, 6, 1, 3, 5, 7]
    r = 0
    for i in range(8):
        r |= (((c >> i) & 1) << xft[i])
    return r


def shdiag_encode_data(in_data):
    ip = 0
    op = 1
    out_data = [0] * (len(in_data) * 2)
    v = (random.randint(0, 0x7f) + 0xf)
    x = shdiag_xchar(v)
    out_data[0] = v
    while ip < len(in_data):
        if in_data[ip] == '\r' or in_data[ip] == '\n':
            out_data[op] = in_data[ip]
            op += 1
            if in_data[ip] == '\n' and ip + 1 < len(in_data):
                x = shdiag_xchar(v)
                out_data[op] = v
                op += 1
        else:
            out_data[op] = (in_data[ip] ^ (x & 0x7f)) + 0xf
            x = (x >> 1) | ((x & 1) << 7)
            op += 1
        ip += 1
    return out_data[:op]


def shdiag_decode_data(in_data):
    ip = 1
    op = 0
    out_data = [0] * (len(in_data) - 1)
    x = in_data[0]
    x = shdiag_xchar(x)
    while ip < len(in_data):
        if in_data[ip] == '\r' or in_data[ip] == '\n':
            out_data[op] = in_data[ip]
            op += 1
            if in_data[ip] == '\n' and ip + 1 < len(in_data):
                x = in_data[ip + 1]
                x = shdiag_xchar(x)
                ip += 1
        else:
            out_data[op] = (in_data[ip] - 0xf) ^ (x & 0x7f)
            x = (x >> 1) | ((x & 1) << 7)
            op += 1
        ip += 1
    return out_data[:op]


def nb30port_open():
    dev = usb.core.find(idVendor=NB30_USB_VID, idProduct=NB30_USB_PID)
    if dev is None:
        return None
    dev.set_configuration()
    cfg = dev.get_active_configuration()
    intf = cfg[(1, 1)]
    ep_in = usb.util.find_descriptor(intf, custom_match=lambda e: usb.util.endpoint_direction(
        e.bEndpointAddress) == usb.util.ENDPOINT_IN)
    ep_out = usb.util.find_descriptor(intf, custom_match=lambda e: usb.util.endpoint_direction(
        e.bEndpointAddress) == usb.util.ENDPOINT_OUT)
    return dev, ep_in, ep_out


def nb30port_close(dev):
    usb.util.dispose_resources(dev)


def nb30port_read(ep_in):
    return ep_in.read(ep_in.wMaxPacketSize, 1000)


def nb30port_write(ep_out, data):
    return ep_out.write(data, 1000)


def main():
    print("YuuSHDIAG v0.2")
    print("Usage: python shdiag.py <SHDIAG_COMMAND>")
    if len(sys.argv) != 2:
        return 1
    while True:
        dev, ep_in, ep_out = nb30port_open()
        if dev is not None:
            break
    res = nb30port_read(ep_in)
    if len(res) > 0:
        res_decode = shdiag_decode_data(res)
        print(''.join(map(chr, res_decode)))
    req = '{}\r\n'.format(sys.argv[1])
    req_encode = shdiag_encode_data(req)
    if 0 < len(req_encode) == nb30port_write(ep_out, req_encode):
        res = nb30port_read(ep_in)
        if len(res) > 0:
            res_decode = shdiag_decode_data(res)
            print(''.join(map(chr, res_decode)))
    nb30port_close(dev)


if __name__ == '__main__':
    main()

最近整理电脑的备份时候翻出来的表格文件,用Office的保存为HTML进行了保存。
大约是去年年尾时候所收集的兆芯CPU的详细信息列表
凑合看吧,也许有用!

ZHAOXIN-L

其中包括的所有商标以和数据版权均属于上海兆芯集成电路有限公司。

这些GUID用于DisplayHdrLevel中的认证项目显示,需要多字符串值(Multi-String)且可叠加使用

VESA DisplayHDR

VESA DisplayHDR 400 (1.0)
20C5A9AF-CD1A-42B1-AA71-4C96A273DEF1
VESA DisplayHDR 400 (1.1)
0D710BC2-6368-4EB2-A829-CBBD45CE3BD2
VESA DisplayHDR 500 (1.1)
C47B4522-B803-47B0-831F-2ED63B56CE79
VESA DisplayHDR 600 (1.0)
D4C5928E-9488-46AF-8DA8-4F996EE4177F
VESA DisplayHDR 600 (1.1)
7134A821-9254-4AF4-9973-95B3FCF720CC
VESA DisplayHDR 1000 (1.0)
78137DFC-3400-412E-B0AF-08120754623A
VESA DisplayHDR 1000 (1.1)
C624859D-304A-4DE8-86DC-8BE82B79527A
VESA DisplayHDR 1400 (1.0)
0D710BC2-6368-4EB2-A829-CBBD45CE3BD2
VESA DisplayHDR 1400 (1.1)
3CA0903F-99E0-46FB-9BEC-DE023507BEF0
VESA DisplayHDR 2000 (1.1)
80931144-16F1-4710-91F4-2E66713B134D
VESA DisplayHDR 400 True Black (1.0)
1A6CBAFB-15FF-4CF0-AD75-12360E9B9F4A
VESA DisplayHDR 400 True Black (1.1)
FB4CB49B-F5A8-4084-800C-EB38E9CA16DE
VESA DisplayHDR 500 True Black (1.0)
86413F8C-0CDB-4D49-81F7-06BB64A8FED1
VESA DisplayHDR 500 True Black (1.1)
3B6DAA9E-3794-4D85-897E-93AE990D275D
VESA DisplayHDR 600 True Black (1.1)
9AD0FB30-006E-49FE-AA15-8F65F28A476B
VESA DisplayHDR 1000 True Black (1.1)
9C5D5F59-1FA8-4D2B-87DD-2E3B2BFF37D5

DOLBY

Dolby Vision
6363AA90-A651-4154-A9E1-2D765C08E68F

NVIDIA

NVIDIA G-SYNC ULTIMATE
35FBD985-74F0-4271-AC61-295F11D71AEF

AMD

AMD Freesync Premium Pro
F9310F0E-93B2-4A58-8642-17358D8CB2E3

最近因为笔记本的SSD出现了奇怪的问题,所以选择了重装系统,在重装系统之后,发现Dolby Atmos这些组件,由于软件组件设备的存在,一旦连接网络,即可通过Windows Update自动重新下载和安装,但是Dolby Vision这类额外组件,则需要手动补全。但在通过Microsoft Store的已购买功能找到Dolby Vision客户端安装后,发现调整设置没有反应,在Dolby Access中直接没有杜比视界选项,播放Dolby Vision视频也没有了Logo提示和色彩校准,视频内容也完全是偏色的状态。
FixDBV_MissingVision
在网上大量爬帖,得知Dolby Vision是需要校准+密钥二合一文件才可在Windows下打开,于是便在网上大量寻找我这个型号的校准+密钥二合一文件,然而并不存在任何单独下载,其他OEM的方案是通过显示器驱动来解决,然而联想并未给我这个型号提供任何显示器驱动。
由于跟联想的这个产品的PM有联系,但联系他他给出的方法是建议送附近的维修站,然而我目前在国外,并不具备去到服务站的条件。其后,他又给出了一个建议,使用联想海外版本的DDRS(Lenovo Digital Download Recovery Service)服务,自行制作官方恢复盘进行恢复(可在此处找到)
但在刻录完启动盘之后,从U盘启动,发现其要格式化整个硬盘来重装系统,并且恢复到Windows10,我便不太想直接恢复了,开始对恢复盘的文件内容逆向。
其大部分内容即为IMZ文件(本体)+CRI文件(基本信息)来组成
FixDBV_RecoveryFileDetails
由于CRI是文本文件,则很方便的就寻找到了DolbyVision所对应的CRI和IMZ文件
FixDBV_CriInEditor
同时发现其所谓的IMZ,也仅仅只是7z压缩包而已
但是,在解压时,却又出现了问题
FixDBV_PasswordError
发现其中提到的Password=lenovo其实根本不对!这里有坑!所以又继续爬贴,爬Github,终于在一个小众论坛和Github上找到了解决方案(这里这里),在此感谢DenizOezmen的逆向!
不过那时候很无聊,所以把Github上提供的Python版本给移植到了C++和Javascript,代码和可执行文件如下
网页版

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string PwChars = "k`gybs0vampjd";
    string Password;
    cout << "Lenovo Recovery Image IMZ File Password Analyzer\n(C)Yuu 2022\n";
    cout << "Password in CRI File>>";
    cin >> Password;
    cout << "Real Password: ";
    for (int i = 0; i < Password.length(); i++)
    {
        cout << (char)(PwChars[Password[i] % 13] - (i % 3) + 2);
    }
    cout << endl;
    system("pause");
    return 0;
}

下载可执行文件(Windows-x86)
执行后,成功得到了真实密码!
FixDBV_RealPassword
也终于成功解压出了所有文件!
FixDBV_RealFile
在对其setup.cmd进行简单的分析过后,发现其实并不用那么复杂,其全部过程即为
1.先行安装"Headedcode"或"Headlesscode"文件夹内的appx

注:
1.如果你的设备使用DolbyAccess来管理所有杜比组件,则安装Headlesscode中的appx(即为Store中的Dolby Vision Extension)
2.如果你的设备跟我的一样,使用单独的Dolby Vision App来管理,则需要安装Headedcode中的appx

2.再通过管理员权限执行其中的ProvisionDolbyVision.exe,有可能会报错但不影响使用
3.此时重启设备,你会发现你的DolbyVision回来了!
FixDBV_Succeed

注:
通过对ProvisionDolbyVision.exe的分析,发现其只是检测MONITOR/后的字符串,然后从ICMS文件夹中,选定要复制的文件,将文件名改为PQCONFIG.DV后,复制到<SYSTEM_DRIVE>:\WINDOWS\System32\spool\drivers\color目录下而已,如果这个一键程序无法正常工作,则可以通过直接复制的方法来解决问题