2018年11月1日木曜日

[Linux] PCIe Endpoint Driver with Character Device Driver


好一陣子沒寫東西了
來紀錄一下最近做的東西

最近從 Windows driver 轉做 Linux driver
不知道是不是找資料的方式不對
還是 Linux 更新太快了
一直都找不到比較新的資料

Linux kernel 都已經更新到 4.19 了
結果大部分的資料都還在講 2.6.x
雖然絕大部分都可以向下相容
但總是有些東西沒辦法用

所以這篇用來紀錄一下
前陣子用 kernel 4.x 做 PCIe EP device driver 開發的東西
說是紀錄
但也就只是放個 pcie 的 device driver 的樣板上來而已
本來偷懶想直接全部複製貼上
不過因為有很多東西不能公開
所以只好貼通用的部份上來了

是說完整的內容太長了
所以還是分段貼好了...OTL

理論上下面這串程式直接做成一個.c檔
建成一個 kernel module 應該就可以用了
但不保證我手殘有很大的機會敲錯就是了...w



#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/init.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/of_pci.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/version.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/phy/phy.h>

#include <linux/irqreturn.h>
#include <linux/fs.h>
#include <linux/signal.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/dma-mapping.h>
#include <linux/wait.h>
#include <linux/completion.h>


#ifndef PCI_EP_ENGINE_DRIVER_VERSION_NUMBER
#define PCI_EP_ENGINE_DRIVER_VERSION_NUMBER "1.0"
#endif

#ifndef PCI_EP_ENGINE_NAME
#define PCI_EP_ENGINE_NAME "pcie_ep_device"
#endif

#ifndef PCI_EP_ENGINE_VENDOR_ID
/* 0x11ab for Marvell Technology Group Ltd.*/
/* ref. http://pci-ids.ucw.cz/read/PC */
#define PCI_EP_ENGINE_VENDOR_ID 0x11ab 
#endif

#ifndef PCI_EP_ENGINE_DEVICE_ID
/* 0x0023 for Marvell 88pa6220 */
#define PCI_EP_ENGINE_DEVICE_ID 0x0023
#endif

#ifndef PCI_EP_ENGINE_CLASS_ID
/* 0x08: Generic system peripheral */
/* 0xXX80: System peripheral */
/* 0xXXXX00: Program interfaces */
#define PCI_EP_ENGINE_CLASS_ID 0x088000
#endifux

#ifndef PCI_EP_ENGINE_CLASS_MASK
/* i am not sure what this is ... */
#define PCI_EP_ENGINE_CLASS_MASK 0xffffff00
#endif

// 0: for static; 1: for dynamic
#define PCI_EP_ENGINE_DYNAMIC_ALLOC_CHR_NUM 1

#ifndef PCI_EP_ENGINE_ALLOC_CHR_COUNT
#define PCI_EP_ENGINE_ALLOC_CHR_COUNT 1
#endif

#ifndef PCI_EP_ENGINE_CHAR_MAJOR
#define PCI_EP_ENGINE_CHAR_MAJOR 0
#endif

#ifndef PCI_EP_ENGINE_CHAR_MINOR
#define PCI_EP_ENGINE_CHAR_MINOR 0
#endif

#define PCI_EP_ENGINE_FUNCTION_IN_PRINT \
    printk(KERN_ALERT "%s(%d): in\n", __func__, __LINE__)

#define PCI_EP_ENGINE_FUNCTION_OUT_PRINT \
    printk(KERN_ALERT "%s(%d): out\n", __func__, __LINE__)

#define PCI_EP_ENGINE_PRINT_FUNCTION_CALLER \
    printk(KERN_ALERT "Caller is: %pS\n", __builtin_return_address(0))

static struct class * g_p_pci_ep_engine_class;
static struct device * g_p_pci_ep_engine_device;

static struct pci_device_id pci_ep_engine_ids[] = {
//{PCI_EP_ENGINE_VENDOR_ID, PCI_EP_ENGINE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* how to determine the RC or EP with same VID & DID ? */
{ PCI_DEVICE_CLASS(PCI_EP_ENGINE_CLASS_ID, PCI_EP_ENGINE_CLASS_MASK) }, /* determine the EP which is a System peripheral */
{0,}
};
MODULE_DEVICE_TABLE(pci, pci_ep_engine_ids);

struct pci_ep_engine
{
    struct pci_device * pci_dev;
    struct cdev chr_dev;
    dev_t devno;
    unsigned long bar0_physical;
    unsigned long bar0_virtual;
    unsigned long bar0_length; 
} ep_engine_device;

static int pci_ep_engine_probe(struct pci_dev * pdev, const struct pci_device_id * id);
static void pci_ep_engine_remove(struct pci_dev * pdev);
static irqreturn_t pci_ep_engine_interrupt(int irq, void * pdev);

static int pci_ep_engine_probe(struct pci_dev * pdev, const struct pci_device_id * id)
{
    int i;
    int result;
    PCI_EP_ENGINE_FUNCTION_IN_PRINT; 
    pci_set_drvdata(pdev, ep_engine_device.pci_dev);

    if (pci_enable_device(pdev)) {
        PCI_EP_ENGINE_DEBUG_ERR("failed' pci_enable_device\n");
        result = -EIO;
        goto end;
    }

    pci_set_master(pdev);
    ep_engine_device.pci_dev = pdev;

    if (unlikely(pci_request_regions(pdev, PCI_EP_ENGINE_NAME))) {
        printk(KERN_ALERT "%s(%d): failed pci_request_regions\n", __func__, __LINE__);
        result = -EIO;
        goto enable_device_err;
    }

    // get bar 0 physical & virtual address
    ep_engine_device.bar0_physical = pci_resource_start(pdev, 0);
    if (ep_engine_device.bar0_physical < 0) {
        printk(KERN_ALERT "%s(%d): failed: pci_resource_start\n", __func__, __LINE__);
        result = -EIO;
        goto request_regions_err;
    } else {
        printk(KERN_ALERT "%s(%d): got pci resource: bar 0 physical address(0x%08x)\n", __func__, __LINE__, ep_engine_device.bar0_physical);
    }

    // get bar 0 virtual address
    ep_engine_device.bar0_length = pci_resource_len(pdev, 0);
    if (ep_engine_device.bar0_length != 0) {
        ep_engine_device.bar0_virtual = (unsigned long)ioremap(ep_engine_device.bar0_physical, ep_engine_device.bar0_length);
        printk(KERN_ALERT "%s(%d): bar 0 physical remap to virt: 0x%08x\n", __func__, __LINE__, ep_engine_device.bar0_virtual);
        printk(KERN_ALERT "%s(%d): bar 0 length: %lu\n", __func__, __LINE__, ep_engine_device.bar0_length);
    } else {
        printk(KERN_ALERT "%s(%d): failed: pci_resource_len get zero!!\n", __func__, __LINE__);
    }

    // enable MSI
    result = pci_enable_msi(pdev);
    if (unlikely(result)) {
        printk(KERN_ALERT "%s(%d): failed: pci_enable_msi\n", __func__, __LINE__);
        goto free_bar0;
    } else {
        printk(KERN_ALERT "%s(%d): enable msi succeeded.\n", __func__, __LINE__);
    }

    result = request_irq(pdev->irq, pci_ep_engine_interrupt, 0, PCI_EP_ENGINE_NAME, ep_engine_device.pci_dev);
    if (unlikely(result)) {
        printk(KERN_ALERT "%s(%d): failed: request_irq\n", __func__, __LINE__);
        goto enable_msi_error;
    } else {
        printk(KERN_ALERT "%s(%d): request_irq succeeded.\n", __func__, __LINE__);
    }

    goto end;
  
enable_msi_error:
    pci_disable_msi(pdev);
free_bar0:
    iounmap((void*)ep_engine_device.bar0_virtual);
request_regions_err:
    pci_release_regions(pdev);
enable_device_err:
    pci_disable_device(pdev);
end:
    PCI_EP_ENGINE_FUNCTION_OUT_PRINT;
    return result;   
}

static void pci_ep_engine_remove(struct pci_dev * pdev)
{
    PCI_EP_ENGINE_FUNCTION_IN_PRINT;

    free_irq(pdev->irq, ep_engine_device.pci_dev);
    pci_disable_msi(pdev);

    iounmap((void*)ep_engine_device.bar0_virtual);
    pci_release_regions(pdev);
    pci_disable_device(pdev);

    PCI_EP_ENGINE_FUNCTION_OUT_PRINT;
}

static irqreturn_t pci_ep_engine_interrupt(int irq, void * dev)
{
    PCI_EP_ENGINE_FUNCTION_IN_PRINT;
  
    // do something at here 

    PCI_VIRTIO_ENGINE_FUNCTION_OUT_PRINT;
    return IRQ_HANDLED;
}

static struct pci_driver pci_ep_engine_driver = {
    .name = PCI_EP_ENGINE_NAME,
    .id_table = pci_ep_engine_ids,
    .probe = pci_ep_engine_probe,
    .remove = pci_ep_engine_remove,
};

static int pci_ep_engine_open(struct inode * inode, struct file * file)
{
 PCI_EP_ENGINE_FUNCTION_IN_PRINT;
 PCI_EP_ENGINE_FUNCTION_OUT_PRINT;
 return 0;
}

int pci_ep_engine_close(struct inode * inode, struct file * file)
{
 PCI_EP_ENGINE_FUNCTION_IN_PRINT;
 PCI_EP_ENGINE_FUNCTION_OUT_PRINT;
 return 0;
}

long pci_ep_engine_unlocked_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
{
 PCI_EP_ENGINE_FUNCTION_IN_PRINT;
 PCI_EP_ENGINE_FUNCTION_OUT_PRINT;
 return 0;
}

static ssize_t pci_ep_engine_read(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
{
 PCI_EP_ENGINE_FUNCTION_IN_PRINT;
 PCI_EP_ENGINE_FUNCTION_OUT_PRINT;
 return 0;
}

static ssize_t pci_ep_engine_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos)
{
 PCI_EP_ENGINE_FUNCTION_IN_PRINT;
 PCI_EP_ENGINE_FUNCTION_OUT_PRINT;
 return 0;
}

static struct file_operations pci_ep_engine_fops = {
    .owner = THIS_MODULE,
    .open = pci_ep_engine_open,
    .release = pci_ep_engine_close,
    .unlocked_ioctl = pci_ep_engine_unlocked_ioctl,
    .read = pci_ep_engine_read,
    .write = pci_ep_engine_write,
};

static int pci_ep_engine_driver_init(void)
{
    int ret;
    PCI_EP_ENGINE_FUNCTION_IN_PRINT;
    PCI_Ep_ENGINE_PRINT_FUNCTION_CALLER;
    
    ret = pci_register_driver(&pci_ep_engine_driver);
    if (ret < 0) {
        printk("failed: pci_register_driver\n");
        return ret;
    }

#if    PCI_EP_ENGINE_DYNAMIC_ALLOC_CHR_NUM
    ret = alloc_chrdev_region(&ep_engine_device.devno, 0, PCI_EP_ENGINE_ALLOC_CHR_COUNT, PCI_EP_ENGINE_NAME);        
#else
    ep_engine_device.devno = MKDEV(PCI_EP_ENGINE_CHAR_MAJOR, PCI_EP_ENGINE_CHAR_MINOR);
    ret = register_chrdev_region(ep_engine_device.devno, PCI_EP_ENGINE_CHAR_MINOR, PCI_EP_ENGINE_ALLOC_CHR_COUNT, PCI_EP_ENGINE_NAME);
#endif
    if (ret < 0) {
        printk("failed: register_chrdev_region\n");
        return ret;
    }

    cdev_init(&ep_engine_device.chr_dev, &pci_ep_engine_fops);
    ret = cdev_add(&ep_engine_device.chr_dev, ep_engine_device.devno, PCI_EP_ENGINE_ALLOC_CHR_COUNT);
    if (ret < 0) {
        printk("failed: cdev_add\n");
        return ret;
    }

    g_p_pci_ep_engine_class = class_create(THIS_MODULE, PCI_EP_ENGINE_NAME);
    g_p_pci_ep_engine_device = device_create(g_p_pci_ep_engine_class, NULL, ep_engine_device.devno, NULL , PCI_EP_ENGINE_NAME);

    PCI_EP_ENGINE_FUNCTION_OUT_PRINT;
    return 0;
}

static void pci_ep_engine_driver_exit(void)
{
    PCI_EP_ENGINE_FUNCTION_IN_PRINT;

    device_destroy(g_p_pci_ep_engine_class, ep_engine_device.devno);
    class_destroy(g_p_pci_ep_engine_class);

    cdev_del(&(ep_engine_device.chr_dev));
    unregister_chrdev_region(ep_engine_device.devno, PCI_EP_ENGINE_ALLOC_CHR_COUNT);
    pci_unregister_driver(&pci_ep_engine_driver);

    PCI_EP_ENGINE_FUNCTION_OUT_PRINT;
}

module_init(pci_ep_engine_driver_init);
module_exit(pci_ep_engine_driver_exit);

MODULE_AUTHOR("yuutan");
MODULE_LICENSE("GPL");
MODULE_VERSION(PCI_EP_ENGINE_DRIVER_VERSION_NUMBER);
MODULE_DESCRIPTION("ep engine over PCIe: device driver with character device driver");



2018年7月4日水曜日

[Linux] 在 linux 下用 command 搜尋資料夾底下所有檔案內容文字的方法


記性太差,用了那麼多次還是不記得,只好乖乖的把它紀錄下來了。


find <path> -name "<file>" -exec grep -H "<content_string>" {} \; > <output_file>
find * -name "*.*" -exec grep -H "something" {} \; > output.txt


平行化:
find <path> -name "<file>" parallel -j<N> grep -H <content_string> {} > <output_file>
find * -name "*.*" | parallel -j8 grep -H "something" {} > output.txt

試了一下 

結果看起來好像更慢了 

也許是因為是個5400RPM的HDD的關係 

可能換顆SSD會快一點

 
就這樣沒了

2018年6月19日火曜日

[OpenCV] Cross Compiling OpenCV with non-free modules for Linux ARM


最近 Ubuntu 用的比較習慣,所以這次還是使用 Ubuntu 來做 cross compiling。

這次一樣又很偷懶直接拿一台現有的機器來試試看

為了方便起見,這次用 ubuntu 18.04 x64 的系統

直接抓 opencv master branch 下來做。

至於為什麼要做 master branch ...

好像沒有為什麼,就是偷懶不想花時間去找其他版本來用XD

需要的東西

1. Virtualbox 任何可以安裝 Ubuntu 18.04 x64系統的版本都好
2. Ubuntu 18.04 x64 系統映像檔

然後用預設的方式安裝系統

在裝好後乾淨的 Ubuntu 系統上什麼都不要做

連更新什麼的都不要...O(>﹏<)O

雖然其實做了也不影響就是ww

然後直接在 Ubuntu 上打開終端機(alt + F2 → gnome-terminal, ctrl + alt + T)

在 terminal 裡照著下面的指令一行一行的敲就好...

沒有意外的話最後就會出現結果了XD

安裝必要的套件

$ sudo apt-get install git repo bison build-essential zip curl cmake
$ sudo apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi

建立工作路徑

$ mkdir -p <work_directory>/opencv_build
$ cd <work_directory>/opencv_build

把 OpenCV master 分支的 source 抓下來

$ git clone https://github.com/Itseez/opencv.git
$ git clone https://github.com/opencv/opencv_contrib.git

除了抓 opencv 的 source 之外

non-free 模組是另外的放的

所以才要在把 opencv_contrib 抓下來

建置 OpenCV master 分支

在建置之前先建立一下輸出路徑
$ mkdir -p build
$ cd build

如果不需要 non-free 模組就執行下面這行
$ cmake -DSOFTFP=ON  -DCMAKE_TOOLCHAIN_FILE=../opencv/platforms/linux/arm-gnueabi.toolchain.cmake ../opencv

如果需要 non-free 模組就執行下面這行
$ cmake -DSOFTFP=ON  -DCMAKE_TOOLCHAIN_FILE=../opencv/platforms/linux/arm-gnueabi.toolchain.cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib/modules ../opencv

最後就是建置啦
$ make
$ make install


基本上到這邊只要 make 跑完沒有錯誤就全部結束了...

然後建置完的輸出檔案會再 install 資料夾下

如果資料夾下有東西的話

應該就是有正常結束了

=====


相關來源:

Building / Cross Compiling OpenCV for Linux ARM
http://www.ridgesolutions.ie/index.php/2013/05/24/building-cross-compiling-opencv-for-linux-arm/

Repository for OpenCV's extra modules
https://github.com/opencv/opencv_contrib

2018年5月27日日曜日

[AOSP] 用 Ubuntu 18.04 建立 Android 系統建置環境


在 Ubuntu 上使用 AOSP(Android Open Source Project) 編譯 android 系統

過了好多年,從之前的 ubuntu 14.04 到現在的 ubuntu 18.04

AOSP 都從 5.x 進化到 8.x 了

感覺現在連建置都變簡單了

所以只好再打一篇來記錄一下

之前好像還要打些什麼的

不過內容太多了就懶的寫了

這篇也偷懶直接複製之前的來修改w

所以這篇依然是 AOSP 的 master 的建置



為了減少除錯的時間同樣這次直接使用乾淨的系統(。-_-。)

手邊好像也沒有多餘的機器所以直接開 VM 來做...

等預算夠再來搞一台實體機好了XD

需要的東西

1. Virtualbox 任何可以安裝 Ubuntu 18.04 x64系統的版本都好
2. Ubuntu 18.04 x64 系統映像檔


然後用預設的方式安裝系統

雖然說是預設...

但是根據上面的夠強大的硬體...

基本上有三個東西要調整...

一個叫做 CPU

一個叫做 記憶體

一個叫做 硬碟

CPU 可能的話請給到 2 個核心以上

記憶體如果可能的話請給到 8GB 以上

硬碟容量分配無論如何請不要小於 100GB ← \_(・ω・`)ココ重要!

因為實際整個建置完之後的系統容量就超過 80G 了


在裝好後乾淨的 Ubuntu 系統上什麼都不要做

連更新什麼的都不要...O(>﹏<)O

雖然其實做了也不影響就是ww

然後直接在 Ubuntu 上打開終端機(alt + F2 → gnome-terminal, ctrl + alt + T)

在 terminal 裡照著下面的指令一行一行的敲就好...

沒有意外的話最後就會出現結果了XD



安裝必要的套件

$ sudo apt-get install git repo gnupg flex bison gperf build-essential zip curl zlib1g-dev libc6-dev lib32ncurses5-dev lib32z1 x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev g++-multilib tofrodos python-markdown libxml2-utils software-properties-common xsltproc libx11-dev:i386 liblz4-tool android-tools-adb android-tools-fastboot google-android-build-tools-installer bzip2 libbz2-dev libbz2-1.0 libghc-bzlib-dev squashfs-tools pngcrush schedtool dpkg-dev make optipng maven python-mako python3-mako python python3 syslinux-utils

安裝 OpenJDK

和之前不同的是,這次只需要 OpenJDK 就行了
$ sudo apt-get install openjdk-8-jdk

設定 git/repo

$ mkdir ~/bin
$ curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
$ git config --global user.email "android"
$ git config --global user.name "android"

user.email 和 user.name 的 "android"可以是任意的名稱

所以隨意就好XD

設定環境變數


再來就是要 build 整個專案了...

在 AOSP 中有許多分支

這裡只記錄 master 分支 (現時點的AOSP master 分支版本為 8.1)

這邊跟之前的不一樣,這次不再需要對 JAVA 做設定了

所以這個步驟可以直接跳過(*^▽^*)


把 AOSP master 分支的 source 抓下來

這邊要注意的是 source 很多而且很大...

所以下完指令後就可以去睡覺了...XD
$ repo init -u https://android.googlesource.com/platform/manifest
$ repo sync -j8
這裡的 sync 的參數 -j8 是根據現在正在執行這個指令的電腦的CPU資源決定的

可以不寫讓它用預設的方式執行也可以

8 指的是現在這台電腦的核心數

理論上越多就越快...

所以也可以給 -j16 或 -j24 之類的數字

沒那麼多的話給 -j2 或 -j4 也可以XD



建置 AOSP master 分支

再建置之前先重新讀取資源
$ source build/envsetup.sh

再來就是執行建置的動作啦...
$ lunch aosp_arm-eng
$ make -j8
至於選擇 aosp_arm-eng 則是因為現在手機大部分都是這個規格XD

其實這還有其他選項就是了...

有興趣可以直接下 lunch 指令看XD

而這裡的 -j8 和 上面的 -j8 是一樣的意思

不過個人的習慣是 8G 的記憶體會給 -j4 然後 4G 的記憶體會給 -j2

至於為什麼o(‧"‧)o...好像也沒為什麼...就只是壞習慣而已XD

然後因為 android 是個巨大的專案...

所以下完 make 指令之後又可以去睡覺了...(´▽`*)

另外題外話一下

根據網路上找到的資料是用 intel xeon 8C16T 的 CPU 配 24GB 的記憶體

建置需要花 37 分鐘的時間

然後這次我拿 intel m7-6y75 開 VM 分資源 2C2T 的 CPU 配 8G 的記憶體

建置花了超過 9.5 個小時...Σ(゚д゚) エッ!?

用 AMD R7-1700 開 VM 分資源 8C8T 的 CPU 配 8G 的記憶體

只要 1 個小時 50 分鐘就結束了。

看來選 CPU 是一件很重要的事ww



基本上到這邊只要 make 跑完沒有錯誤就全部結束了...

然後建置完的輸出檔案會再 out/target/product/generic 資料夾下

最重要的有 system.img、userdata.img 和  ramdisk.img 三個映像檔

一定要確認這三個檔案有沒有存在...XD


最後就是把好不容易建好的系統放到模擬器上面執行了...


模擬測試

$ emulator

嗯...就這麼一個指令而已XD

然後就慢慢等模擬器自己動作了XD

沒意外的話就會在模擬器上面看到自己建置的 Android 系統了XD

有意外的話就只好慢慢 debug 啦~~(σ≧▽≦)σ

...

其實一定會有意外啦....ε=ε=┏( >_<)┛

因為模擬器預設的資源非常少...

所以會一直 crash 或是運作不順之類的XD

其實還有很多東西要設定...

不過這篇主要是在寫環境建置

所以模擬器設定就省略不寫了XD


=====


相關來源:

android - building the system
https://source.android.com/source/building.html

2017年12月20日水曜日

[C/C++] 點陣 bitmap 的 header 格式

這篇沒什麼特別的內容。

只是記錄一下 1 bit 的點陣圖格式。

B/W 1 bit 的點陣圖 header 是 62 Bytes 不是 64 Bytes。

#pragma pack(push, 1)

typedef struct tagBITMAPHEADER

{

WORD type;
DWORD bmp_file_size;
WORD reserved_1;
WORD reserved_2;
DWORD offset;


DWORD header_size; // 40 bytes
DWORD bmp_width;
DWORD bmp_height;
WORD plane;
WORD bpp;
DWORD compression; // 0
DWORD raw_data_size;
DWORD ppm_x;
DWORD ppm_y;
DWORD  biClrUsed;         // colors used
DWORD  biClrImportant;    // important colors

 // Palette Data 8 Bytes
DWORD palette_data_1; // 0x000000
DWORD palette_data_2; // 0xFFFFFF

} BITMAPHEADER;

#pragma pack(pop)





2017年5月19日金曜日

[Windows] 幫自己的exe檔建立自己的數位簽章

這篇只做快速產生數位簽章的方法,其他原理跟理論和規則什麼都就不寫了。

所以這篇只會有幾個指令而已。

首先會需要一些工具。
這個簽證工具在 windows sdk 裡面。
所以先下載個 sdk 套件
Windows Software Development Kit (SDK) for Windows 8
https://dev.windows.com/en-us/downloads/windows-8-sdk

雖然他寫 for Windows 8
不過基本上 windows 8.1 10 也都適用
或是不放心一定要用 windows 10 SDK 也是可以
Windows 10 SDK
https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk

然後就是製作數位簽章了
就只有3行指令

makecert -a sha1 -b 01/01/2003 -e 12/31/2099 -cy authority -eku 1.3.6.1.5.5.7.3.3 -sv myCA.pvk -r -n "CN=my_name, E=mail@domain.com" myCA.cer
cert2spc myCA.cer myCA.spc
pvk2pfx -pvk myCA.pvk -spc myCA.spc -po 1234 -pfx myCA.pfx -f

做好之後中間那些檔案都不重要了
只要有最後產生的 pfx 檔就可以進行簽證了

所以接著就是幫 exe 檔簽證
指令只有1個
但是因為 sha1 已經停了
所以還要再加簽一個 sha256
所以就變成了2行指令

signtool sign /f myCA.pfx /p 1234 /t http://timestamp.verisign.com/scripts/timstamp.dll /v "filename.exe"
signtool sign /fd sha256 /f myCA.pfx /p 1234 /as /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /v "filename.exe"

然後程式的屬性中就會出現數位簽章的標籤了

因為剛剛簽證做了2次
第一次是 sha1
第二次是 sha256
所以看起來會像下面這張圖這樣


然後點進去詳細裡面
就可以看到剛剛製作 CA 的時候自己設定 CN 這個選項的結果了


大致上數位簽章這樣就完成了
但比較重要的一點
因為這個是沒有經過認證的簽章
所以它還是有可能會被當作不安全的簽章


相關來源:

HowTo: Create self-signed certificates with MakeCert
http://www.virtues.it/2015/08/howto-create-selfsigned-certificates-with-makecert/

[デジタル署名]2016年以降のハッシュアルゴリズムSHA-1廃止について
http://qiita.com/yaju/items/b9b5f06d875d7ef52a9e

Signtoolでの署名方法
https://knowledge.symantec.com/jp/support/bms-support/index?vproductcat=BMS&vdomain=VERISIGN.JP&page=content&id=SO23053&actp=LIST&viewlocale=ja_JP&locale=ja_JP&redirected=true

VisualStudioを入れずに自己署名環境を作る
https://chai99.wordpress.com/2007/10/08/visualstudio%E3%82%92%E5%85%A5%E3%82%8C%E3%81%9A%E3%81%AB%E8%87%AA%E5%B7%B1%E7%BD%B2%E5%90%8D%E7%92%B0%E5%A2%83%E3%82%92%E4%BD%9C%E3%82%8B/

VisualStudioを入れずに自己署名環境を作る
http://d.hatena.ne.jp/chai99/20071008/1191824241


2016年10月27日木曜日

[作業系統] Windows 7 x64 無法正常更新

這篇記錄一下 win 7 x64 在安裝完後,那該死的 Windows Update 一直卡在 檢查更新...

不知道微軟在搞什麼系統越做越神奇了

Windows 10 都出了那麼久了

Windows 7 就算要放棄也不要故意搞得那麼糟糕呀= =

就像下面這張圖這樣

足足等了 72 小時它依然還在檢查那不知道是有多重要的更新

這根本就是壞掉了吧...(´・ω・`)


↑ 正在檢查更新...

試過了一堆有的沒的方法

最後竟然要下載補丁= =

KB3102810:x64 系統的 Windows 7 更新
https://www.microsoft.com/zh-TW/download/details.aspx?id=49540

然後依然是等很久的檢查更新

但是終於會動了!!