bloggerads

2016年11月23日 星期三

x86 architecture : Graphic UMA Frame buffer

傳統的顯卡控制方式是透過A/B Segment MMIO來輸出螢幕,但只有128K MMIO address, 顯然這樣的空間不夠用。現在的內顯都會在DRAM上"偷"一塊Memory做為輸出顯示用,系統上是看不到這塊Memory的,而這塊Memory稱為UMA frame buffer。一般在系統上看到系統顯示的記憶體遠小於所插的Dram記憶體,一大部分就是被frame buffer挖走的,至於frame buffer的size是可以在Bios選單去改變設定的。

UMA frame buffer之所以特殊是,他宣告為MMIO resource,但實際上decoder會將含有此address的cycle再forward給memory. 示意圖如下:



一般CPU bus的 traffic control 設計通常會先看這筆cycle是否往MMIO (C2P cycle),若不是則再看是否往Memory (C2M cycle),若都不是的話,則透過報錯機制回報錯誤(EBMC, MCA...)。

而外插式顯卡本身有自己的DRAM, 雖然都會要求MMIO resource, 但使用的是自己的記憶體。

Keyword: UMA( Unified Memory Architecture), Frame buffer, Graphic

2016年11月15日 星期二

g++ : libgcc_s_dw2-1.dll is missing

解決某些Windows平台在執行exe檔時,找不到libgcc_s_dw2-1.dll。缺少的這個dll應該是C++的library
我的g++版本(gcc -v): 4.8.1

解決方法就是在compile code 時加入 -static-libgcc  -static-libstdc++ 參數把所需要的library包進去

如下:
g++ -o main main.cpp 改成 
g++ -o main -static-libgcc  -static-libstdc++ main.cpp

2016年11月11日 星期五

使用DeviceIoControl::IOCTL_DISK_GET_LENGTH_INFO 獲取 Disk 大小


一般若要得到Sata硬碟或Usb硬碟Size,須要透過傳遞PASS_THROUGH參數來下Identify command,而參數須符合ATA command/ SCSI command spec, 使用上比較麻煩。

WinApi提供了一個比較通用的方式(IOCTL_DISK_GET_LENGTH_INFO)來得到,如下:



#include <windows.h>
#include <winioctl.h>
#include <stdio.h>

unsigned long long GetDiskLengthIoctl(const char *dsk)
{
  HANDLE hDisk = CreateFile( dsk,
                            GENERIC_READ,
                            FILE_SHARE_VALID_FLAGS,
                            0,
                            OPEN_EXISTING,
                            0,
                            0);
  if(hDisk == INVALID_HANDLE_VALUE)
    {
      printf("Could not open the disk. GetLastError() returned ", GetLastError());
      return 0;
    }
  GET_LENGTH_INFORMATION gli;
  DWORD ret;

  DeviceIoControl( hDisk,
                   IOCTL_DISK_GET_LENGTH_INFO,
                   0,
                   0,
                   &gli,
                   sizeof(gli),
                   &ret,
                   0);

  CloseHandle(hDisk);
  return gli.Length.QuadPart;
}
int main()
{

  const char *Disk = "\\\\.\\PhysicalDrive0"; // or \\\\.\\C:
  printf("size = %d (GB)\n", GetDiskLengthIoctl(Disk)/1024/1024/1024);
  printf("Lba = %x \n", GetDiskLengthIoctl(Disk)/512);

}

2016年8月5日 星期五

ATA : SATA-to-USB and SSD

由於USB的方便攜帶跟普及性,所以現在市售走USB protocol 的外接硬碟非常多,大部分的構造都是一顆SATA硬碟搭配SATA-to-USB  轉卡。還有些人是自行購買SATA-to-USB  轉卡透過USB port來外接硬碟 or SSD。接 SSD這樣的用法是有隱憂的,接下來解釋原因。

以上的架構(SATA過轉卡轉USB), 如果想傳原生的ATA Command給硬碟,則必須穿過  SATA-to-USB  轉卡才能將ATA command傳給碟機。方法是透過呼叫  DeviceIoControl 來發出  SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER以前在硬碟廠寫相關Utility (Update FW/ Identify...), 就是透過這個protocol發出ATA 給硬碟。

能夠在作業系統底下Access碟機,以硬碟廠的角度可以提供FAE做初期的檢測(看Smart table / 下一些Vendor Specific的command來判斷FTL/GC出了什麼樣的問題)當然還有最重要的update FW

2016年7月1日 星期五

UEFI : 編譯文件

現有的Project要升級EDK2, 因此整理一下使用EDK2的經驗,並把所理解的做個簡單記錄:

首先,INF/DEC/DSC/FDF file是標準編譯UEFI code所需要準備的,在 AMI code裡DSC/FDF file是AutoGen出來的,而且因為AMI有自己的編譯介面,所以編譯AMI code還須要準備 "SDL""CIF", "VEB" "ldl"檔。

以下介紹INF/DEC/DSC files

● 先定義名詞: $(Arch)  (對像是何種architecture)
Arch Description
IA32 X86 32位CPU
X64 X86 64位CPU
IPF Itanium Processor Family
ARM  
EBC EFI Byte Code

● $(MORDULE_TYPE)  (如SEC, PEI_CORE, PEIM, DXE_CORE,...)

2016年6月24日 星期五

UEFI : BuildOptions (Compiler Options)

用來access IO的變數若不宣告成volatile,但又怕因為最佳化而沒有實際access到IO的話,可以改Compiler Options 關掉最佳化編譯更改UEFI 的Compiler Options, 可以選擇一次改全部 modules 或只改單一個 module,在EDK2都是透過修改DSC file。

1. 更改單一個 module 的 compiler options

[Components]

PackageNamePkg/NameOneDxe/NameOneDxe.inf {
    <BuildOptions>
    MSFT:*_*_*_CC_FLAGS = /Od
}

2016年6月5日 星期日

C# : from in where let select, 資料庫語法


public class Example_of_From_In_Let_Select
{
    public static void Main(string[] args)
    {
        string names = "Mr.Adam,Mrs.Eva,Mr.Henry,MS.May";
        var array = names.Split(',');
       
        var result = (
                from name in array
                where (name.Substring(0, name.IndexOf('.')) == "Mr" )
                let new_name = name + "<Male>"
                select new_name
            );
       
        foreach(string x in result)
            Console.WriteLine(x);
    }
}

/////// Output ///////
Mr.Adam<Male>
Mr.Henry<Male>