pretty code

2018年12月27日 星期四

孩子的學習不能等

在考慮了快一個月之後,我還是下訂了 Kindle Oasis 2。

可惜的是想買的保護套都沒有運送台灣。

運費被收了 USD 20.98,關稅被預收了 USD 14.68。

換算下來大約要 NTD 9600,似乎也沒有比網拍便宜到哪。

但是孩子的學習不能等呀XD


2018年12月26日 星期三

ImportError when using pyinstaller to package up wxPython

如果是使用 Python 3.7
Pyinstaller with wxPython 會出現 wx._core import error

試著改用 Python 3.6 即可

底下是我測試能用的版本

Python 3.6.8 32 bit
PyInstaller 3.4
wxPython 4.0.3

2018年12月19日 星期三

MicroPython on UEFI

MicroPython 是一個 Python3 的子集
其目的是用在 microcontrollers 上或是一些受限制的系統
但並不支援所有的語法

MicroPython differences from CPython

tianocore porting MicroPython 目的是用來取代之前 porting 的 Python 2.7
原因是之前 porting 的效能較不好
也不能存取一些 UEFI Services or hardwares

目前專案位於以下路徑
https://github.com/tianocore/edk2-staging/tree/MicroPythonTestFramework/MicroPythonPkg

如果這個東西的成熟度夠高
應該會適合拿來撰寫 UEFI Application
畢竟整套環境是想用來當作 TestFrameWork 用的


2018年12月14日 星期五

UEFI Application - Stack overflow

最近在幫同事看一個問題
覺得很有趣,故記錄一下解題思路

同事在 build code 時,發現一個 link error
正在產生程式碼
已完成程式碼產生
UefiApplicationEntryPoint.lib(ApplicationEntryPoint.obj) : 
error LNK2001: 無法解析的外部符號 __chkstk

網路查了一下,是因為 VC compiler 檢查到某些 function  有 stack 問題時
便會在 code 中插入 __chkstk 這個 check function

網路看到的解法都是放大 stack size
可以在 INF 檔案編譯選項中加入 /GsXXXXX
但據實測的結果是一點用處都沒有
stack size 還是維持在 32K 左右

後來試著在 INF 檔案編譯選項中加入 /FAcs 選項
此選項會產生 assembly 檔案
副檔名為 .cod

接著在 UDK\Build\程式路徑中
用 grep 搜尋 __chkstk 關鍵字
便可以看到是那個 function 被插入了 __chkstk

底下是我模擬的結果
很明顯的看到 rsp register 被保留了 32776 這麼大的空間(char LocalVar[32768])
當然會造成 stack overflow



2018年12月12日 星期三

Python 正規表示式用法

Python 在使用 re 時
記得 pattern 要包含其他需要的字串(.*)

舉例來說
我想尋找每行有 "ERROR " 字眼的字串
re pattern 要寫成 "ERROR .*"
否則找到的都會只有 "ERROR " 本身

底下是針對規則的進階用法
把想要特別提出來的寫成如下形式
(?P<name>正規表示式)

就可以更方便的找出對應的資料


import re

ERROR_PATTERN = 'ERROR.*Test: (?P<TEST>[0-9]+).*Address: (?P<ADDR>[0-9A-F]+)'

errMsg = '''
2068-09-12 22:06:48 - [MEM ERROR - Data] Test: 6, CPU: 1, Address: 101B8F330, Expected: FFFF5FFF, Actual: FFFFDFFF
2068-09-12 22:06:48 - [MEM ERROR - Data] Test: 6, CPU: 1, Address: 103B8F310, Expected: FFFF5FFF, Actual: FFFFDFFF
2068-09-12 22:06:50 - [MEM ERROR - Data] Test: 6, CPU: 3, Address: 119FEA5F0, Expected: FFFF7FDF, Actual: FFFFFFDF
2068-09-12 22:06:50 - [MEM ERROR - Data] Test: 6, CPU: 3, Address: 11BFEA5D0, Expected: FFFF7FDF, Actual: FFFFFFDF
2068-09-12 22:20:53 - [MEM ERROR - Data] Test: 6, CPU: 2, Address: 10466E930, Expected: FFFF7FEF, Actual: FFFFFFEF
2068-09-12 22:20:53 - [MEM ERROR - Data] Test: 6, CPU: 2, Address: 10666E910, Expected: FFFF7FEF, Actual: FFFFFFEF
2068-09-12 22:20:53 - [MEM ERROR - Data] Test: 6, CPU: 0, Address: 10D6CC9B0, Expected: FFFF7EFF, Actual: FFFFFEFF
2068-09-12 22:20:53 - [MEM ERROR - Data] Test: 6, CPU: 0, Address: 10F6CC990, Expected: FFFF7EFF, Actual: FFFFFEFF
'''

res = re.findall(ERROR_PATTERN, errMsg)

print(res)


輸出結果
[
    ('6', '101B8F330'), 
    ('6', '103B8F310'), 
    ('6', '119FEA5F0'), 
    ('6', '11BFEA5D0'), 
    ('6', '10466E930'), 
    ('6', '10666E910'), 
    ('6', '10D6CC9B0'), 
    ('6', '10F6CC990')
]

2018年12月11日 星期二

GoBus

程式碼

剛來這家公司時
為了早日了解專案順便吃便當
常常看 code 看到忘了時間
於是便有了這支小程式的誕生

此程式的原理是去 parse 公車網站
並顯示出還有多久公車會來
程式寫好後,便設定工作排程器固定時間執行
時間一到程式會顯示在右下角
這樣一來就不會忘記回家了

因為只是支小程式
故並未使用 Thread 只是偷懶使用 Timer
當遇到網路連線太久時,UI 便會無回應(顯示空白)
不過目前夠用就好

2018年12月7日 星期五

Single Python executable binary on Windows

I used "PyInstaller" and I used these parameters to build it

"pyinstaller -D -F -w main.py"

My "main.py" is a "wxPython" project and it works well.

Caution: If you use Python 3.7, you will encounter wx._core import error. You can use Python 3.6 to fix this error.

第一支 UEFI Application - Python code

最近有一個需求

希望使用者設定完參數後
可以連續做一定次數的測試
其目的是希望測試結果的穩定性

平常我們初始化測試都是透過 Web-UI
不過骨子裡其實也是走 HTTP Web API 模式
故在 UEFI 下使用 C 寫並不是太困難

由於還有 download 測試報告
並做一些 disk 資料夾的備份等工作
我最後還是決定使用 Python 來撰寫

不得不說
使用 Python 開發真是飛快
我先在 Windows 下寫好花不到半天
遇到不會的就用關鍵字 google

不過實際跑在 UEFI Shell 上
才發現會遇到一些坑

幸好我的程式每個功能都是 function
只要修改幾個 function 即可
但前提在測試時,不要一次跑完
不然根本不知道程式那邊出錯

目前已知問題有
1. os.rename 會使得原始檔案不見
2. copy_threee 也有同樣的問題
3. 點開頭的檔案在使用 Shell command cp 時會有問題

雖然說來輕鬆
但我可是加了 2 小時班
如果 Python on Windows 我給 90 分
Python on UEFI 我只會給 55 分

2018年11月27日 星期二

大陸亞馬遜購書

前一陣子發現 Kindle 可以支援自訂字型﹝需升級版本到最新﹞。

在裝了特殊簡體字型後,便可以看到繁體中文的內容,於是便申請了一個大陸亞馬遜帳號,底下是步驟及問題整理。

1. 不同國家亞馬遜帳號沒有互通,需要各自申請,網路上說不能用同一組 email,但我測試是沒有問題,記得密碼不要一樣。

2. 需在我的設備及內容裡的設置,將國家改成中國,才可以購買電子書,我這裡是用集運公司的地址。

3. 如果上網的 IP 不在中國,購買幾本書後﹝我在買了 8本後﹞,便會被鎖住,可以聯絡線上客服幫忙解鎖,一次可以開放 20 本,之後被鎖住就再開,如果覺得麻煩,可以考慮用 VPN 之類的方式上網。

線上客服

2019/06/17 更新
由於線上客服選項無法出現,嘗試用電子郵件聯繫,但一個禮拜都沒有收到回信。後來發現在線上客服頁面多試幾次後,有機會跳出線上客服選項,也順利的請客服幫忙解鎖成功。

另外,我查了一下幾家知名的 VPN,目前只剩 PureVPN 的網站有顯示支持大陸,但在買了一個月的帳號後,使用 Chrome Extension 發現並沒有 China  的伺服器可以選擇,待安裝其他版本軟體來確認。

2019/06/20 更新
經安裝 Windows 軟體實測,可以連到大陸無誤,詳此篇文章

2018年11月19日 星期一

Use mongodump and mongorestore with authentication

如果當初設定 MongoDB 時,有設定帳號密碼
則 dump and restore 時,都需要指定相關資訊

假設 ip 192.168.1.1, port 27017, user abc, password abc, database def

mongodump -h 192.168.1.1 -p 27017 -u abc -p abc /db:def /out:"xxxxxx"
mongorestore -h 192.168.1.1 -p 27017 -u abc -p abc /db:def "xxxxxx"
   
如果有設定 root 帳號,則不必指定 /db: 參數,會備份所有 database(含 admin)
相反的如果有針對 database 設定存取帳號,則一定要加上 /db: 參數

2018年11月13日 星期二

MongoDB 備份與還原

目前知道的備份有 2 種方式(針對 single server)

1. 直接複製 MongoDB db and log 的上層目錄,如果是在 Windows 下,需要先停止服務
2. 使用 mongodump -p portNumber /out:"folder path",dump 的資料夾會位於 "folder path"

至於還原的話
1. 直接複製回去即可
2. mongorestore /drop "folder path",在還原前會先砍掉舊資料

2018年11月2日 星期五

Javascript 非同步 pattern

還沒有 Promise, asyc / await 前
在撰寫非同步程式時
其實 code 的邏輯不太好看
又容易會有 callback hell 的問題

今天想了一下,其實可以用以下概念來處理此類問題

我們以常見的從資料庫撈資料來看
大概注意幾個重點即可

1. 在 function 內寫出一連串要做事的 function and callback
2. 上述 function 不要寫成變數,否則會有 undefined 的問題(hoist)
3. 相關的 function 可以照執行順序寫好,方便閱讀


function getDataFromDB(callback) {
    console.log("start connect to DB");
    connectDB(connectDBCB);

    function connectDB(cb) {
        setTimeout(() => {
            console.log("connect to DB done \n");
            cb(null, "fake handle");
        }, 2000);
    }

    function connectDBCB(err, conn) {
        console.log("start get data");
        getData(conn, getDataCB);
    }

    function getData(conn, cb) {
        setTimeout(() => {
            console.log("get data done \n");
            cb(null, conn);
        }, 2000);
    }

    function getDataCB(err, conn) {
        setTimeout(() => {
            console.log("prepare data to back");
            callback(err, [1, 2, 3]);
        }, 2000);
    }
}

getDataFromDB((err, data) => {
    console.log(err, data);
});

2018年11月1日 星期四

Build wxWidgets Project in Linux

OS: Ubuntu

使用 apt-get install 相關程式
apt-get install libwx*
apt-get install wx3.0*

執行 wx-config --cxxflags
-I/usr/lib/x86_64-linux-gnu/wx/include/gtk2-unicode-3.0 -I/usr/include/wx-3.0 -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread

執行 wx-config --libs
-L/usr/lib/x86_64-linux-gnu -pthread   -lwx_gtk2u_xrc-3.0 -lwx_gtk2u_webview-3.0 -lwx_gtk2u_html-3.0 -lwx_gtk2u_qa-3.0 -lwx_gtk2u_adv-3.0 -lwx_gtk2u_core-3.0 -lwx_baseu_xml-3.0 -lwx_baseu_net-3.0 -lwx_baseu-3.0

綜合上面參數,使用 g++ 便可以成功編譯

假設你寫了一支 Test.cpp,裡面簡單的創建一個視窗,你也可以這樣下指令來直接編譯
g++ Test.cpp `wx-config --cxxflags --libs` -o Test
如果需要顯示中文,記得使用 UTF8 編碼



Test.cpp

#include <wx/wx.h>

class Test : public wxFrame
{
public:
    Test(const wxString& title)
        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, wxSize(400, 200))
    {
        Center();
    }
};

class MyApp : public wxApp
{
public:
    bool OnInit()
    {
        Test *test = new Test(wxT("醉裡挑燈看 Code"));
        test->Show(true);
        return true;
    }
};

wxIMPLEMENT_APP(MyApp);

Javascript substr

以前再取子字串時都習慣使用 substr
今天才知道這個 function 不算是標準的 ECMAScript Spec(僅在附錄)
故建議是不要使用 substr
可以用 substring or slice 來代替

Annex B (normative)
Additional ECMAScript Features for Web Browsers

The ECMAScript language syntax and semantics defined in this annex are required when the ECMAScript host is a web browser. The content of this annex is normative but optional if the ECMAScript host is not a web browser.

NOTE This annex describes various legacy features and other characteristics of web browser based ECMAScript implementations. All of the language features and behaviours specified in this annex have one or more undesirable characteristics and in the absence of legacy usage would be removed from this specification. However, the usage of these features by large numbers of existing web pages means that web browsers must continue to support them. The specifications in this annex defined the requirements for interoperable implementations of these legacy features.

These features are not considered part of the core ECMAScript language. Programmers should not use or assume the existence of these features and behaviours when writing new ECMAScript code. ECMAScript implementations are discouraged from implementing these features unless the implementation is part of a web browser or is required to run the same legacy ECMAScript code that web browsers encounter.

Javascript 浮點數轉整數

Javascript 的數字類型是 64 位元的浮點數

以前在轉 C code 時
遇到類似 3/2 的語法都用 parseInt(3/2) 來取代

正規來說,應該要用 Math.floor(3/2)
也讓不懂 Javascript 的人比較好懂 code 的意義

2018年10月31日 星期三

Javascript variable hoisting

以前只是大概知道
並沒有認真搞懂

使用 var 宣告的變數 scope
是在最接近它的 function 裡

故在 a 處,因為 variable hoisting 的關係
x 變數是存在的,但是仍未賦值
故印出來的結果是 undefined

假設我們沒有宣告 var x = 2
則 a 處就會觸發 "ReferenceError: x is not defined"
function foo() {
    console.log(x);      // a

    var x = 2;

    console.log(x);
}

foo();

2018年10月25日 星期四

GPL 之我見

GPL 對寫程式的人應該都很不陌生

一般來說,用到 GPL 程式碼的後續程式
理論上都會視為 GPL 的感染

那如果開發者只是單純的使用 GPL 的程式呢?
假設說是資料庫好了

比如說 MariaDB 是 GPL 授權
我寫了一個 IoT Gateway 的 message collection system
我使用了 MariaDB 來儲存資料
這時我的整個 system 的程式是否也變成 GPL 呢?

以前曾經聽過一種說法(僅針對 GPLv2)
如果你可以證明你的 system 不需要使用 MariaDB 也可以單獨執行
那就可以不用變成 GPL

故你的 system 需確保這件事
因為 SQLite 是使用 Public Domain 的授權
只要你的 system 沒有 MariaDB 也可以使用 SQLite 正常運作
一般來說就會視為跟 MariaDB 間是獨立的關係

當然如果你選擇在安裝包中包含 MariaDB
你必須準備好 MariaDB 相關的文件與程式碼
2018/10/29 Update
即使你的作品符合上述獨立關係的定義
但當你將 MariaDB 和你的作品一起發佈時
整個作品都會受到 GPL 之約束
GPL 對其他許可獲得者的授權將延伸至整個作品
不論作品是誰寫的
(These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.)

以上是我個人的理解
故最安全的方式應該是將作品和 GPL 的元件分開發佈

今天在林誠夏先生的 "GPL 條款對於衍生程式的判定標準與其授權拘束性的擴散範圍(上)" 這篇文章看到這段

GPL 授權條款也明文表達了一個授權拘束性的例外規定,那就是、具有「獨立性與可區分性(Separate and Independent,註三)」的軟體元件,並不會因為僅與 GPL 授權元件同在一個軟體專案的架構下運作,就被歸類為 GPL 授權元件的衍生著作。所以、若是符合「Separate and Independent」這個例外條件,此時軟體專案便可以被認定為一個統合的聚合作品 (aggregation),此時散布整個聚合的軟體專案時,就只需要提供該 GPL 授權元件的程式源碼,而不一定要將 GPL 元件的授權拘束性擴及到其他自行編寫且獨立運作的個別元件。那麼、接下來的問題就是,所謂的「獨立性與可區分性」,是不是已經有一個公定標準,或是多數 GPL 授權元件的開發者皆已得到共識的參考範圍?

應該有符合我以前聽過的說法吧?

相關連結
http://blog.ez2learn.com/2011/11/25/taiwan-software-lacking-of-open-source/

2018年10月18日 星期四

go-seo SEO 小工具

之前就很想幫 blog 某些文章增加搜尋度
故研究了一下要如何實現

後來發現只要下的關鍵字可以在 google 結果中找到 blog 頁面
這時再去點取該 blog 頁面
Blogger 系統便會在該 blog 頁面瀏覽次數加 1
於是就達成了我的目標

如此一來,我最受歡迎的頁面應該就不是大台北行政區圖了吧

相關程式請詳
https://github.com/tylpk1216/go-seo

2018年10月16日 星期二

Javascript async / await 速成



01. await 後面接的是 1 個 Promise,一定會等待此 Promise 狀況 ready 

02. new Promise((resolve, reject) => {
        // ok 
        resolve(xx);
        return;
        
        // error
        reject(new Error("xxx"));
    });

03. async function 一定要回傳 1 個 Promise
    async function asyncXXX(xx) {
        try {
            
            // return value, 會被隱性轉成 Promise
            return 1;
            
            // Use static method
            return Promise.resolve(xx);
            
        } catch(err) {
            return Promise.reject(err);        
        }
    }
    
    asyncXXX(xx).then((xx) => {
        console.log(xx);
        
        // 如果有 return Promise 會形成 Promise chain
        return 1;    
        return new Promise(...);
    }).catch((err) => {
        // err is Error type
        console.log(err.message);
    });

04. Promise 只是確保在 Promise 控制的範圍內可以照順序
    在呼叫 Promise 時 本身還是非同步
    故底下會先印出 "after" 而不是 "in then"

    async function test() {
        return Promise.resolve();
    }

    test.then(() => {
        console.log("in then");
    });

    console.log("after");

05. async / await 只是語法糖,骨子裡還是 Promise 的運用

2018年10月5日 星期五

Copy object in Javascript

在 Javascript 中,複製 1 個 object,只是類似做 1 個 reference
故當修改了外面傳進來的 object  後
原先外面的那個 object 也會被修改

故我們要用底下第 2 種寫法以避免 bug
var newDataArg = dataArg;
newDataArg.xxx = "xxxx"; // wrong - dataArg is modified.

var newDataArg = Object.assign({}, dataArg);
newDataArg.xxx = "xxxx";

2018年9月27日 星期四

x86 Assembly in Linux - part 6

寫組語前除了用紙筆安排要用的暫存器外,最好也是分段撰寫,這樣比較方便除錯。

大部份的錯誤都是常數忘記加上 "$",或是 instruction 的單位用錯

即使如此,code 還是常常不如預期,幸好我們可以很簡單的用 GDB 來 debug。

相關步驟如下:
"as -gstabs add debug information to object
"objdump -D a.out | less" or "nm a.out" 利用此步驟找到相關變數或 label 的 address
"gdb a.out" 執行 GDB
"b label name" 對要監控的 label 下斷點
"display /i $pc" 顯示當前執行的組語
"run" 執行程式
斷點觸發
"info all-registers" 觀看目前所有暫存器值
"p $eax" 觀看 eax
"p abc" 觀看 variable abc
"x/x address" 觀看 address hex value
"step" 單步執行

當然也可以使用包裝 GDB 的 GUI tool。

x86 Assembly in Linux - part 5

因為趕專案沒什麼時間,諷刺的是我也是因為專案才開始學組語
當初設想的目標就是可以用組語寫出猜數字的小遊戲

扣掉重覆的 function 行數約 361 行
如果用 Go 或是 C 大概只需要不到 100 行

雖然寫出了猜數字組語版
但 "Programming from the Ground Up" 還是停留在第 5 章沒有進度
之後大概也沒有時間再看了

安西教練,我好想打籃球 !!!

https://github.com/tylpk1216/1A2B/blob/master/guessnum.s

2018年9月20日 星期四

x86 assembly in Linux - part 4

在高階語言的世界裡 printf 就像喝水一樣
往往是最常用的 debug 工具之一

但在組語的世界裡
在還不會呼叫 C 語言函式庫前
你是無法跟螢幕打交道的

幸好我們還是可以透過 system call 來做這件事
用的是 write system call
差別在 file descriptor 是 STDOUT ($1)

底下是個包裝好的函式
接收 1 個參數,指向 C語言字串 (null-terminated string) 的 address 位址
參數傳遞方式是使用 stack

.type myprint,@function
myprint:
    pushl %ebp
    movl %esp, %ebp

    # get msg address
    movl 8(%ebp), %ecx

    # get msg length
    movl $0, %edx

start_loop:
    cmpb $0, (%ecx)
    je end_loop

    incl %ecx
    incl %edx

    jmp start_loop

end_loop:
    movl $4, %eax
    movl $1, %ebx
    movl 8(%ebp), %ecx
    int $0x80

    movl %ebp, %esp
    popl %ebp
    ret

x86 assembly in Linux - part 3

雖然 "Programming from the Ground Up" 還沒看完
在知道了如何呼叫 linux system call 後 (exit)
便想找 1 個簡單的 system call 來試試

看來看去 mkdir 算是相對簡單的
不過卻讓我卡了 2 天

直到今天才恍然大悟自己錯在哪裡
原來我只顧著 create directory
卻沒有 call exit system call
難怪死得不明不白

.section .data
name:
    .string "MK"

.section .text

.global _start

_start:
    movl $39, %eax
    movl $name, %ebx
    movl $0777, %ecx
    int $0x80

    movl $1, %eax
    movl $0, %ebx
    int $0x80

x86 assembly in Linux - part 2

"Programming from the Ground Up" 的作者建議寫組語時
最好是拿紙筆把要用到的暫存器安排一下
寫起 code 來會比較順暢

昨天回家洗澡時就想到
part 1 的 example 做了一些很不必要的動作
也多用到一些不必要的暫存器

舉例來說
%ebx 存起的是 memory address
也是我存放要比較整數的 list (array)

原本 for loop 都會用 %edi 來當 index variable
但在這個 case 其實是不必要的
因為我們本來就可以對暫存器直接做加減

start_loop:
    incl %edi

    movl $4, %edx
    imull %edi, %edx
    addl %ebx, %edx

start_loop:
    addl $4, %ebx

2018年9月19日 星期三

x86 assembly in Linux - part 1

目前看的書是網路很推薦的 "Programming from the Ground Up"
由於這本書介紹的是 32 位元的組語寫法
故在編譯成 64 位元的 code 時會有問題

此時需指定 --32 to as and -m elf_i386 to ld

as source.s --32 -o source.o
ld source.o -m elf_i386 -o source.out

另外,如果在 call function 時,想把 label's address pass to function
在 label 前面,需加上 "$"

底下是個 example,max function 會幫忙把資料組裡的最大值找出
並將回傳值放進 %eax register

.section .data
list:
    .long 31,2,199,7,0

.section .text

.global _start

_start:

    pushl $list
    call max
    addl $4, %esp

    movl %eax, %ebx
    movl $1, %eax
    int $0x80

.type max,@function
max:
    pushl %ebp
    movl %esp, %ebp

    movl 8(%ebp), %ebx

    movl $0, %edi

    movl $4, %edx
    imull %edi, %edx
    addl %ebx, %edx
    movl (%edx), %eax

start_loop:
    incl %edi

    movl $4, %edx
    imull %edi, %edx
    addl %ebx, %edx
    movl (%edx), %ecx

    cmpl $0, %ecx
    je end_loop

    cmpl %eax, %ecx
    jle start_loop

    movl %ecx, %eax
    jmp start_loop

end_loop:
    movl %ebp, %esp
    popl %ebp
    ret

2018年9月13日 星期四

big-endian and little endian

雖然知道這個的不同
但每次都會忘記記憶體位置的順序
乾脆畫了一個圖來幫助記憶

大概只有 3 個重點
1. 計憶體位置是由低到高
2. 最高位元的資料 (0x12) 先擺就是 big-endian
3. 相反就是 little-endian



2018年8月28日 星期二

Javascript Array fill function


var result = Array(5).fill(['-', '-']);

console.log('before', result);

result[0][1] = 'modify result[0]';

console.log('after ', result);


如果 fill 傳進去的是 1 個物件
如上例中的 ['-', '-']

最後 result array 裡面的元素
都會是同 1 個物件的 reference

這會造成明明只是要改 1 個 element
卻變成 5 個 element 都一起生效

真是 1 個神奇的 bug

2018年8月24日 星期五

startup.nsh in UEFI Shell

UEFI Shell 下有一個開機自動執行 tool 的方式,其方式類似 DOS 的 AUTOEXEC.BAT,只是檔名為 startup.nsh

底下是 UEFI Shell Spec 2.2 的說明:

When executing startup.nsh, the shell will search for it first in the directory where the shell itself was launched. If it cannot find the startup.nsh file in that directory or it was not launched from a file system, it will search the execution path defined by the environment variable PATH.
 
由上可以得知,正常放進 USB 裡的 Shell 會位於 EFI\BOOT\,故只要將 startup.nsh 置於此處便可以自動執行。

另外,則是要看 PATH 環境變數是否有定義,Shell 會去裡面對應的位置去尋找 startup.nsh 來執行。

這也解釋了為什麼有些電腦 startup.nsh 不放在 EFI\BOOT\ 便不會自動執行,那是因為系統並沒有 PATH 的變數存在。

2018年8月23日 星期四

Delete file in C

最近分別需要在 Windwos, UEFI, DOS 撰寫同樣的 tool
趁著寫完的空檔,整理一下之前沒有注意到的小細節

在這 3 個系統中,我共用了大部份的 code,只有針對系統的差異做 porting
其中我需要 1 個砍檔案的 function (unlink)

最早我是先在 UEFI 使用這個功能
原本以為只有 UEFI 有

後來在陸續 porting 到 Windows and DOS 時
才發現大家都有這個函數

上網查了一下
這個不是 standard c
而是 POSIX 標準
難怪我的 gcc 也會有 (Windows)

底下是 3 個環境 include header file 的位置
UEFI(UDK code) - <sys/EfiSysCall.h>
Windows(TDM GCC) - <io.h>
DOS(Open Watcom) - <io.h>

2018年7月12日 星期四

UEFI Application - support HTTPS

原本撰寫 UEFI Application with C
關於網路部份我使用的是 HP porting 的 CurlLib
但這裡並沒有加上 HTTPS 的支援
CurlLib可以使用多種 SSL Lib
因為 UDK2014 在 CryptoLib porting 的是 openssl-0.9.8w
故我在這裡是選擇在 CurlLib 中打開 openssl

底下是我的步驟及遇到的問題,還有個人認為的解決方案
0. 使用 VC and UDK2014
1. 依照 "CryptoPkg\Library\OpensslLib\Patch-HOWTO.txt",安裝 openssl
2. Modify "HpNetworkPkg\HpNetworkPkg.dsc",add "OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf" in "[LibraryClasses]"
3. Modify "HpNetworkPkg\HpNetworkPkg.dec",add "../CryptoPkg/Include" in "[Includes]"
4. Modify "HpNetworkPkg\Library\CurlLib\lib\CurlLib.inf",add "CryptoPkg/CryptoPkg.dec" in "[Packages]" and "OpensslLib" in "[LibraryClasses]"
5. Modify "HpNetworkPkg\Library\CurlLib\lib\CurlLib.inf",add "/DUSE_SSLEAY /DUSE_OPENSSL" in "MSFT:*_*_*_CC_FLAGS"

此時會遇到很多 SSL 開頭函數的 Link Error
之所以會有這些問題是 UDK2014 雖然有 porting openssl-0.9.8w
但在 "OpensslLib.inf" 並沒有去編譯相關檔案
舉例來說 "CryptoPkg\Library\OpensslLib\openssl-0.9.8w\ssl" 裡的檔案都不在 "OpensslLib.inf"

故我認為有 2 個方式可以解決
1. Modify "OpensslLib.inf",編譯相關檔案,但我認為這是大工程
2. 使用 UEFI 原生的 HTTP_PROTOCOL,但不確定有沒有支援 HTTPS

留下測試的相關步驟以做記錄

2018年7月6日 星期五

UEFI Application - Python 3rd modules

今天想要試試如何在 UEFI 使用 Python 3rd modules
故挑了一個常用的 requests module 來測試

底下是相關的步驟
我使用的是 UDK 2014

1. pip install requests
2. pip show requests
3. copy step2 的相關 modules to EFI\StdLib\lib\python.27\site-packages
4. uncomment "default_socket_options = [(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)]" in site-packages\urllib3\connection.py, and add "default_socket_options = []"
5. open "signal", "unicodedata", "zipimport", "zlib" in Python\Efi\config.c
6. define "WITH_THREAD" in Python\X64\pyconfig.h
7. add "Python-$(PYTHON_VERSION)/Modules/threadmodule.c" and "Python-$(PYTHON_VERSION)/Python/thread.c" in Python\PythonCore.inf
8. add your thread implement for uefi or you can use mine below. if this file is named "xxxx.h", remember to add "#include "xxxx.h" in Python\Python-2.7.2\Python\thread.c
9. rebuild Python.efi



/*
 * Initialization.
 */
static void
PyThread__init_thread(void)
{
}

/*
 * Thread support.
 */
static int g_id = 123;
long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
    return g_id;
}

long
PyThread_get_thread_ident(void)
{
    return g_id;
}

void
PyThread_exit_thread(void)
{
}

/*
 * Lock support.
 */

typedef struct {
    char             locked; /* 0=unlocked, 1=locked */
} thread_lock;


PyThread_type_lock
PyThread_allocate_lock(void)
{
    thread_lock *lock = (thread_lock*)malloc(sizeof(thread_lock));
    lock->locked = 0;

    return (PyThread_type_lock)lock;
}

void
PyThread_free_lock(PyThread_type_lock lock)
{
    thread_lock *p = (thread_lock*)lock;

    free((void*)p);
}

int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
    thread_lock *p = (thread_lock*)lock;

    int success = p->locked == 0;

    if ( !success && waitflag ) {
        int count = 0;
        while ( p->locked ) {
            count++;
        }
        success = 1;
    }

    if (success) p->locked = 1;
    return success;
}

void
PyThread_release_lock(PyThread_type_lock lock)
{
    thread_lock *p = (thread_lock*)lock;
    p->locked = 0;
}

2018年6月6日 星期三

amazon EC2 預留執行個體初體驗 - 6

今天心血來潮想使用中華電信 4G SSH 進 東京 EC2
只能說結果真是慘不忍睹

難怪之前遠端桌面很不順
連 SSH 都不太行了

雖然我是用 4G
但我想中華光纖應該也好不到哪去


transfer local git repository history to new remote repository

有時候在寫些小程式時
不太想為了這個開個 github repository
但又想享用版本控管的功能
此時便可以開個 local git repository
要備份時就複製整個資料夾即可

等到小程式寫到一定程度
感覺可以放上 github 時
此時就會面臨想要保留 local git history 的問題

查了一下
原來 git 只要簡單下幾個指令即可

1. git remove -v
 
    此步驟是確定這個 local git 還未指定過其他的 remote

2. git remote add name url

    此步驟是把 remote url 取名為 name,之後就可以針對它 push

    注意:如果是拿 github 或是一個其他地方現有的專案,則是使用改變
    (下面只是例子,要變的路徑是 HTTP github 路徑,公司要用的要看公司的 URL 格式)

    git remote set-url origin https://github.com/USERNAME/OTHERREPOSITORY.git 

3. git remote -v

    此指令會看到步驟 2 的 url and name

4. git push name master

    此指令會把 local 的 master push 到 remote 的 name,遠端便會看到相關的 history

2018年5月22日 星期二

amazon EC2 預留執行個體初體驗 - 5

前篇文章提到東京 EC2 到台灣會有一定的網路延遲
之前是憑印象選擇東京

今天偶然看到可以測試速度的網站
就來確認東京是否是最佳解

嗯,看起來應該是沒錯XD


2018年5月18日 星期五

amazon EC2 預留執行個體初體驗 - 4

在 EC2 上執行了 WebServer
並丟了一些測試網頁

從下圖中可以看出
TTFB (Time To First Byte) 的時間比較久

應該還可以再分析什麼

TTFB 的第 1 個 byte 是有包含 header 的
但使用者從瀏覽器看到的是整個 page (rendered)
故 TTFB 的時間很快,不代表使用者看到 page 的時間就很快

不過這也表示了,東京 EC2 到我的測試電腦有一定的網路延遲

amazon EC2 預留執行個體初體驗 - 3

網路真可怕

最近 GPON 家用路由器被發現有漏洞
CVE-2018-10561 and CVE-2018-10562
我新開的 EC2 只要執行Web Server
就發現真的有不明人士在掃

這個漏洞簡單來說
就是有人會去掃主機是否有開啟相關服務
並試著在 URL 加上字串
1. ?images/
2. /GponForm/diag_FORM?images/

如果剛好用到有問題的路由器
便可以執行一些危險指令

有圖有真相


2018年5月17日 星期四

amazon EC2 預留執行個體初體驗 - 2

之前使用 t2.small + Windows Server 2012
遠端連線常常會莫名斷線

現在雖然是 t2.micro + Amazon Linux
但不論是 ssh or WinSCP
連線看起來都正常

也許是遠端連線需要傳輸的資料較多
或是單純的 Windows Server 需要較好的硬體
總之現在在家也可以順利地連到東京 EC2

不過實測 HTTP API 的結果看起來不是很好
requests per second 只有 5.24


2018年5月15日 星期二

amazon EC2 預留執行個體初體驗 - 1

之前為了做實驗都是短暫的 run instance
最近想要開個永久的 EC2 instance
故稍微研究了一下價錢

發現 Windows 還真不是普通的貴
為了不要大幅增加每月支出
故選擇使用預留執行個體計價-標準一年期
作業系統也從 Windows -> Amazon Linux

US/per month TW/per month
EC2(t2.micro) 7.52 241
EBS(gp2) 32G 0.12 x 32 = 3.84 123
Total 11.36 364
*US 使用 1:32
*Tokyo instance

不過從2017年5月開始,個人用戶還要加收 VAT
以台灣來說,需加收 5%
故每月支出約為 383

不算滿意,但還可以接受

底下是在體驗時遇到的問題,記錄一下
01. 預留執行個體只是增加一個收費項目,但實體還是要另行開
02. 要注意是標準還是可轉換的(因為是英文),可轉換的價錢略高
03. 如果需要開 80 port,要在 Security Groups 增加 Inbound rule,不用管 Linux firewall
04. 由於我寫的簡單 Server 是用 9091,但公司有擋連線到奇怪的 port,故一直不成功

2018年5月8日 星期二

Good Golang timing

Mat Ryer 在 Golang UK Conference "Idiomatic Go Tricks" talk 中
寫了一個 timer 的範例

看了這個 code 才知道,自己跟高手的差距有多大
至少我從來沒想到閉包可以這樣用


2018年4月27日 星期五

UEFI network stack

之前在測試 UEFI Application 的網路功能時,都習慣在我自己的小電腦﹝GB-BXi7-4770R﹞上面測試。

一直以來都以為是缺少 Simple Network Protocol,故我有從 UDK 2014 build 出此 driver,只要在 shell 下 load 此 driver,便可以成功使用 network。

最近無意間在 BIOS 選單裡發現下面選項,Boot \ CSM parameters \ Network stack

只要 enable 它後,就不用再手動 load driver 了。

這樣更方便我用自己的電腦驗證公司程式了,不然一塊那麼大的 mother board 放在桌上還得了,重點是還要跟人借 DRAM,一點都不方便。

當然也不用再手動插入 load driver 在我們的 shell script 了,RD 就是要聰明工作才行。

2018年4月18日 星期三

first priority

你所不知道的 C 語言:物件導向程式設計篇

把它排在第一優先好了

ANSI/ISO/IEC 9899-1999

剛在網路上查了一下
電子檔要 US 60

https://webstore.ansi.org/RecordDetail.aspx?sku=INCITS%2fISO%2fIEC+9899-1999+(R2005)

Shit,好想買
又怕沒時間看

看看 Golang 的過過癮好了

2018年4月16日 星期一

2018年4月13日 星期五

C bool type

C 語言從 C99 開始,增加了 bool 這個關鍵字。

嚴格來說是 _Bool,bool 只是 marco,其目的是為了與 C++ 相容。

使用 bool 時,需 include <stdbool.h>。

至於我用的 TDM-gcc-32﹝4.9.2﹞,因為從此版開始,已經有支援一部份的 C99,故很多 C99 功能可以直接用。

但是預設是 -std=gnu89,我們可以看一下網頁說明。


-std
‘gnu89’
        GNU dialect of ISO C90 (including some C99 features). This is the default for C code.

這也說明了為什麼不用指定 -std=c99,就可以使用 bool、"//" C++ 單行註解以及 for loop variable i。

請參考底下連結:
https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/C-Dialect-Options.html#C-Dialect-Options

C 果然還是博大精深,我想我還太嫩了吧。

2018年3月30日 星期五

好想去高雄

由於被老婆大人限制人身自由,故不能隨意去想去的地方。

幸好訂購的東西已經來了,不得不說博客來的東西還是不怎麼好,邊邊有壓到的痕跡,只是不知道問題是出在誰那邊就是了,記得以前偶爾買書也是會這樣,所以我後來都去實體書店買。

趕快來安排一下,決定跟我的寶貝書放在一起,只是要放哪一格呢?





2018年3月16日 星期五

跳出當下

昨天下班到現在,一直在 parsing log 的 code 中鬼打牆

原本 code 已經寫好
故意測試一些 error case
想要把 error line 的訊息列印出來

因為 fgets 會將行尾的 \r \n 視為合法字元
如果列印出來 message 就會多斷行一次

於是寫了幾行 code 濾掉 \r \n
這時卻發現程式陷入了無限迴圈

明明只有幾行 code
不應該是 while loop 呀

後來才發現不是在這幾行 code while loop
而是因為將 \r \n 濾掉
導致昨天寫好的 code parsing rule 改變了

寫程式似乎很容易陷入盲點
總會以為 bug 是剛寫的 code 引起的

其實這樣說也沒錯
只是錯誤不一定就發生在那些 code 中

如果能夠跳出當下
將眼光放遠
不要執著在那幾行 code

現在應該已經改到下一階段了吧

這就是人生呀

2018年3月15日 星期四

c-warning: incompatible implicit declaration of built-in : function 'xxxx'

手上有一個專案
Server 和 Client 都是由我負責

由於使用了不同的程式語言
常常切換時腦袋都覺得快要打結了

更別提我自己慣用的 PHP 和 Golang
導致我常常要在這 4 種語法間切來切去

今天又回到改 Client code 的循環,這次要用 C parse log
這時就會覺得還是高階語言好用

個人習慣將相關功能寫到同一個 .c and .h
由於 parse log 是個新添加的功能
按照慣例,還是增加了新的檔案

為了處理 log 已經搞到頭昏腦脹
指標都不知道指到哪去了
偏偏又出現一堆這個 warning
因為想先完成 parse 功能
故先暫時忽略它

等到完成了 parse log 後
因為看不出來 code 那邊有問題
於是 google 了一下
才發現是沒有 include 用到的函式庫的標頭檔

由於是第一次遇到
感覺很新奇
畢竟我很少用函式沒 include

記錄一下

有興趣的可以看看 purpose 網友的文章

2018年3月13日 星期二

Use PHP to download Youtube video

最近很喜歡聽 "方宥心" 唱歌
加了好幾首 "最美的歌" 到喜歡的影片
於是就想試看看如何用程式來下載影片

網路上其實有很多線上服務可以做到
不過 RD 就是要捲起袖子自己來才有 fu

網路上查了一下
大概是利用 get_video_info 這個 api 配合影片 id
先取得影片 url ,接著就可以 download

舊的作法會再取得 'sig' 並串到 url 裡面(&singature=XXX)
但根據我 2018/03/14 的測試
url 裡面其實就有 'signature'
如果沒有,用 get_video_info 也會沒有
此時這個影片可能也不用下載了
因為一定會失敗
(但是線上服務是可以的)

不過這個 api 並不是官方 release 的
故以後還能不能用並不知道
再來也不是每個影片都能下載

步驟大概如下
1. 手動在 Youtube 喜歡的影片頁面,下載該頁面原始檔
2. 程式 parse 原始檔,找到影片的 id 及 title
3. 使用 get_video_info 取得 mp4 的下載 url
4. 使用 curl 下載檔案

github 連結


<?php

function downloadVideo($id, $title, $url, $video)
{
    $fp = fopen($video, "w");
    if (!$fp) {
        echo "$id $title can't create video file \n";
        return;
    }

    $ch = curl_init();

    if ($ch === false) {
        echo "$id $title curl_init error \n";
        fclose($fp);
        return;
    }

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST , false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER , false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 600);
    curl_setopt($ch, CURLOPT_HEADER , false);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION , true);
    curl_setopt($ch, CURLOPT_AUTOREFERER , true);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36');
    curl_setopt($ch, CURLOPT_FILE, $fp);
    $con = curl_exec($ch);
    curl_close($ch);

    if ($con === false) {
        echo "$id $title download video error \n";
        fclose($fp);
        return;
    }

    fclose($fp);
}

function processVideo($id, $title, $video)
{
    $api = sprintf("http://www.youtube.com/get_video_info?video_id=%s", $id);

    $res = file_get_contents($api);

    if ($res === '') {
        echo "$id $title res is null \n";
        return;
    }

    $params = [];
    parse_str($res, $params);

    if (!isset($params['url_encoded_fmt_stream_map'])) {
        echo "$id $title url_encoded_fmt_stream_map error \n";
        return;
    }

    $s = $params['url_encoded_fmt_stream_map'];
    $streams = explode(',', $s);

    $realURL = '';
    for ($i = 0; $i < sizeof($streams); $i++) {
        $params = [];
        parse_str($streams[$i], $params);

        if (!isset($params['url']) || !isset($params['type']) || !isset($params['quality'])) {
            echo "$id $title params error \n";
            return;
        }

        $url = urldecode($params['url']);
        $type = urldecode($params['type']);
        $quality = urldecode($params['quality']);

        if (strpos($type, 'video/mp4') == 0) {
            $realURL = $url;
            if ($quality === 'medium') {
                break;
            }
        }
    }

    if ($realURL === '') {
        echo "$id $title has no mp4 type \n";
        return;
    }

    //echo "$title, $realURL\n";

    downloadVideo($id, $title, $realURL, $video);
}

// "youtube.txt" is the file that you use browser to save the page of your favorite videos.
$html = file_get_contents('youtube.txt');

$pattern = '/window\[\"ytInitialData\"\] = ({.*});/';

if (!preg_match($pattern, $html, $matchs)) {
    echo "can't find favorites \n";
    return;
}

$s = $matchs[1];

$json = json_decode($s, true);

$songs = $json['contents']['twoColumnBrowseResultsRenderer']['tabs'][0]
              ['tabRenderer']['content']['sectionListRenderer']['contents'][0]
              ['itemSectionRenderer']['contents'][0]
              ['playlistVideoListRenderer']['contents'];

for ($i = 0; $i < sizeof($songs); $i++) {
    $title = $songs[$i]['playlistVideoRenderer']['title']['simpleText'];
    $title = mb_convert_encoding($title, "big5", "utf-8");
    $title = str_replace([' ', '?'], ['', ''], $title);

    $id = $songs[$i]['playlistVideoRenderer']['videoId'];

    //echo "$id $title \n";

    $video = sprintf("%s\\%s.mp4", __DIR__, $title);

    processVideo($id, $title, $video);

    sleep(10);
}

2018年3月2日 星期五

MongoDB PHP example

最近需要測試一下 MongoDB
雖然我很喜歡 Go 語言
但還是直覺認為用 PHP 會比較方便
 
不過網路上的文章大部份都是舊的 PHP Driver 寫法(class MongoClient)
故花點時間把它整理一下

1. 新的用法有分 Low, High Level,High Level 的 code 比較精簡,但兩個都要裝
2. High Level - https://github.com/mongodb/mongo-php-library
3. Low Level - https://github.com/mongodb/mongo-php-driver
4. 兩者都是官方 release 的(官方也有提供其他語言的 Library)
5. 我使用的版本 PHP 7.0.8, MongoDB 3.6

官方說明

High Level - Query

require 'vendor/autoload.php';

$connectStr = 'mongodb://user:password@localhost:27017/databaseName';

try {
    $client = new MongoDB\Client($connectStr);

    $collection = $client->databaseName->collectionName;
    
    $records = $collection->find([]);

    foreach ($records as $item) {
        echo "_id = $item->_id \n";
    }

} catch (MongoDB\Driver\Exception\ConnectionTimeoutException $e) {
    echo $e->getMessage() . "\n";
}

High Level - Insert

require 'vendor/autoload.php';

$connectStr = 'mongodb://user:password@localhost:27017/databaseName';

try {
    $client = new MongoDB\Client($connectStr);

    $collection = $client->databaseName->collectionName;
    $collection->insertOne(['b' => 'CCC']);

} catch (MongoDB\Driver\Exception\ConnectionTimeoutException $e) {
    echo $e->getMessage() . "\n";
}


2018年3月1日 星期四

Rufus dos 冷知識

Rufus 是一個製作 dos 開機碟的工具。

原本以為 Rufus 是把開機相關檔案包進 .h 檔案裡,後來看到網路上的文章,才知道 Rufus 的 MS-DOS 是從 Windows 裡的檔案解壓縮出來的,﹝C:\Windows\system32\diskcopy.dll﹞。

這也解釋了為什麼在 Windows 10 下無法製作 MS-DOS 開機碟,因為 Windows 10 已經沒有這個檔案了。

src/dos.c

/*
 * Rufus: The Reliable USB Formatting Utility
 * DOS boot file extraction, from the FAT12 floppy image in diskcopy.dll
 * (MS WinME DOS) or from the embedded FreeDOS resource files
 * Copyright © 2011-2017 Pete Batard 
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */

/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */

2018年2月27日 星期二

debug binary 檔案

有時候在 parsing log 時,可能因為 log 很大,故開啟時需要很久的時間﹝VIM 在開幾百 MB 檔案時的速度還可以﹞。

如果我們有類似底下的工具,在 Windows 下工作起來就會很方便,可以指定要顯示的行數,幫助我們快速看到內容,使用 C 語言開發不到 100 行即可。


2018年2月26日 星期一

grep binary 檔案

使用 grep parse log 時
如果 log 裡面有非 ASCII 字元時,比如說 0x00
此時 grep 會誤認為檔案為 binary 檔案
故無法 line by line 顯示

此時只要簡單加上 --text 選項即可

MongoDB connection URI

如果 MongoDB 有設定 auth 認證
連線字串大概會類似下面這樣
mongodb://username:password@localhost:27017

由於此字串是用 '@' 來分隔帳密設定及伺服器 IP
假設密碼也有用到 '@' 就會造成切割字串的問題

此時只要遵照 URI encode 的規則
將特殊字元 encode 即可

不過不同程式語言 API 的實做可能不同
PHP 只要 encode 特殊字元即可
其他語言也許是用 options array 的方式來設定帳密
這部份就得參考各 API 的說明文件

2018年2月14日 星期三

Init MongoDB database with javascript

MongoDB Version:3.6

Steps:
1. run mongod
2. run mongo
3. load('xxxx.js')
4. run "init()"

the content of xxxx.js

var d_admin = {
    user: 'd_admin',
    pwd: 'xxxx',
    roles: [
        {
            role: 'readWrite',
            db: 'test'
        }
    ]
}

var d_user = {
    user: 'd_user',
    pwd: 'xxxx',
    roles: [
        {
            role: 'read',
            db: 'test'
        }
    ]
}

var admin = {
    user: 'root',
    pwd: 'xxxx',
    roles: [
        {
            role: 'root',
            db: 'admin'
        }
    ]
}

function init() {
    db = connect('localhost:27017');
    db = db.getSiblingDB('admin');
    db.createUser(admin);

    db = db.getSiblingDB('test');
    db.createCollection('collection1');
    db.createCollection('collection2');
    db.createUser(d_admin);
    db.createUser(d_user);
    db.getLastError();
}

2018年1月3日 星期三

UEFI NVRAM 小研究

NVRAM is non-volatile RAM that is used in EFI to store variables that need to persist between boots. 

BIOS 選項理論上應該是儲存在 NVRAM 裡,UEFI Shell 有一個 command "dmpstore",我們可以利用它來看目前有那些變數。

另外,也許可以利用下面服務及 function 來動態存取變數。

    //
    // Variable Services
    //
    Status = RowPointer ( SocketFD,
                          pPort,
                          "GetVariable",
                          (VOID *)gRT->GetVariable,
                          NULL );
    if ( EFI_ERROR ( Status )) {
      break;
    }
    Status = RowPointer ( SocketFD,
                          pPort,
                          "GetNextVariableName",
                          (VOID *)gRT->GetNextVariableName,
                          NULL );
    if ( EFI_ERROR ( Status )) {
      break;
    }
    Status = RowPointer ( SocketFD,
                          pPort,
                          "SetVariable",
                          (VOID *)gRT->SetVariable,
                          NULL );
    if ( EFI_ERROR ( Status )) {
      break;
    }

這篇文章是 kurtqiao 介紹如何調整 BootOrder 的文章,可以參考。

2019/06/19 更新
可以參考我的最新實驗