2017年10月26日 星期四

UEFI Shell

最近需要 pass Shell Env to my shell script
原本以為是很難的事
幸好 UEFI 在 C Lib 中就提供了 setenv 函數

不過事情不是憨人想的那樣
呼叫此 function 會失敗
從 errno 中看到失敗值是 45 表示 unsupport

沒關係除了 setenv,我們還有二個方式
1. UefiShellLib 的 ShellSetEnvironmentVariable(後來才發現 setenv 也是 call 它)
2. 使用 SHELL PROTOCOL

很不幸的 2 個方式都會 gg,回傳的值是 3  (EFI_UNSUPPORTED)
此時直覺是 INF 設定有問題,調整老半天還是搞不定

後來換了 UEFI Shell 後,事情總算解決了
不過此時又跑出一個新的 question

EdkShellBinPkg 還有 ShellBinPkg 裡面都有 Shell Binary
為什麼一個可以成功,一個卻不行
過了一個禮拜終於在 官網 github 找到答案

簡單來說 EdkShellBinPkg 是 v1.0 的 Shell Spec
ShellBinPkg 是 v2.0 的 Shell Spec
我們從下圖的註解便可以得知
需要 UEFI Shell 2.0 的環境才能支援


/**
  set the value of an environment variable

This function changes the current value of the specified environment variable. If the
environment variable exists and the Value is an empty string, then the environment
variable is deleted. If the environment variable exists and the Value is not an empty
string, then the value of the environment variable is changed. If the environment
variable does not exist and the Value is an empty string, there is no action. If the
environment variable does not exist and the Value is a non-empty string, then the
environment variable is created and assigned the specified value.

  This is not supported pre-UEFI Shell 2.0.

  @param EnvKey                 The key name of the environment variable.
  @param EnvVal                 The Value of the environment variable
  @param Volatile               Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).

  @retval EFI_SUCCESS           the operation was completed sucessfully
  @retval EFI_UNSUPPORTED       This operation is not allowed in pre UEFI 2.0 Shell environments
**/
EFI_STATUS
EFIAPI
ShellSetEnvironmentVariable (
  IN CONST CHAR16               *EnvKey,
  IN CONST CHAR16               *EnvVal,
  IN BOOLEAN                    Volatile
  )
{
  //
  // Check for UEFI Shell 2.0 protocols
  //
  if (gEfiShellProtocol != NULL) {
    return (gEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile));
  }

底下分別是 EdkShellBinPkg 和 ShellBinPkg 的 Shell version information







2017年10月16日 星期一

get callback's return value inside synchronous function

最近在幫別人改 Node.js 的 code
由於他的寫法是同步,但是又使用 callback 方式

原本以為在改架構時,可以簡單的改成 return 形式
但卻撞到不知名的 bug
試了一下才知道在 callback 中的 reurn 不等於呼叫 callback 的 function 的 return
如果直接 return,此時的 var a 會是 undefined

抱歉,不熟 Node.js 不知要怎麼形容
記錄一下,以後再來找答案


function test(callback) {
    console.log("in test");

    var usage = Math.floor((Math.random() * 100) + 1);

    if ((usage%2) == 0) {
        callback(true);
    } else {
        callback(false);
    }

    console.log("exit test");
}

function b() {
    console.log("in b");

    var res;
    test(function(result) {
        console.log("in test callback", result);
        /*
        if (result) {
            return true;
        } else {
            return false;
        }
        */
        res = result;
    });

    console.log("after test");
    return res;
}

var a = b();

console.log("after b");
console.log(a);

2017年10月2日 星期一

Golang - cross complie

原本測試 Linux 的電腦最近都用來跑 UEFI
由於不需要鍵盤,故臨時要用 Linux 很不方便
再加上該 Linux 並沒有安裝 Golang,故也沒有相關的設定

幸好,Golang 支援 cross complie
在我工作的 Windows 電腦上
只要簡單設定幾個環境變數
就可以順利的 build 出跨平台 binary

set GOOS=linux
set GOARCH=amd64
go build