<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Programming &#8211; richliu&#039;s blog</title>
	<atom:link href="https://richliu.com/category/computer/programming/feed/" rel="self" type="application/rss+xml" />
	<link>https://richliu.com</link>
	<description>Linux, 工作, 生活, 家人</description>
	<lastBuildDate>Wed, 01 Apr 2026 17:11:06 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Plurk Dark Mode</title>
		<link>https://richliu.com/2026/04/02/6492/plurk-dark-mode/</link>
					<comments>https://richliu.com/2026/04/02/6492/plurk-dark-mode/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Wed, 01 Apr 2026 17:03:31 +0000</pubDate>
				<category><![CDATA[Blog/wiki]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[隨手札記]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Dark Mode]]></category>
		<category><![CDATA[Plurk]]></category>
		<category><![CDATA[Tampermonkey]]></category>
		<category><![CDATA[前端]]></category>
		<category><![CDATA[網頁客製化]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=6492</guid>

					<description><![CDATA[<p>Plurk 的佈景主題只能用在河道上，如果是單一噗的連結，是不會更動到的。像我就很常將一噗另外開一頁來看，沒辦 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2026/04/02/6492/plurk-dark-mode/">Plurk Dark Mode</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Plurk 的佈景主題只能用在河道上，如果是單一噗的連結，是不會更動到的。像我就很常將一噗另外開一頁來看，沒辦法切換 Dark Mode 很困擾。今天跟 Claude 一起 debug，終於將 Plurk Dark Mode 弄出來了。第一段 CSS 可以直接貼上，單一噗的頁面則需要靠 Tampermonkey 來達到修改 theme 的目的。結論：CSS 真不是人可以輕易改動的東西。</p>



<figure class="wp-block-image size-full is-resized"><img fetchpriority="high" decoding="async" width="1508" height="870" src="https://richliu.com/wp-content/uploads/2026/04/image-1.png" alt="" class="wp-image-6493" style="width:617px;height:auto" srcset="https://richliu.com/wp-content/uploads/2026/04/image-1.png 1508w, https://richliu.com/wp-content/uploads/2026/04/image-1-600x346.png 600w, https://richliu.com/wp-content/uploads/2026/04/image-1-768x443.png 768w, https://richliu.com/wp-content/uploads/2026/04/image-1-816x471.png 816w" sizes="(max-width: 1508px) 100vw, 1508px" /></figure>



<p>河道的不太方便，不過色系是一樣的。</p>



<span id="more-6492"></span>



<p>Plurk CSS，貼到自訂佈景主題就可以了</p>



<pre class="wp-block-preformatted">body {<br />    background: none;<br />    color: black;<br />}<br />#top_bar a, #top_login a, #dashboard_holder a, #footer a {<br />    color: black !important;<br />}<br /><br />/* 噗的內容區塊 - 用較亮的暗灰，跟黑色背景區分 */<br />.plurk_cnt {<br />    background-color: #484848 !important;<br />    color: #eee !important;<br />}<br /><br />.plurk_cnt .text_holder {<br />    background-color: #484848 !important;<br />    color: #eee !important;<br />}<br /><br />/* 連結改成淡藍 */<br />.plurk_cnt a {<br />    color: #7ab8ff !important;<br />}<br /><br />/* 回應區 */<br />.list .plurk_cnt {<br />    background-color: #505050 !important;<br />    color: #eee !important;<br />}<br /><br />/* 回應區 hover */<br />.list .plurk_cnt :hover {<br />    background-color: #666 !important;<br />    color: #fff !important;<br />}<br /><br />/* 修掉殘留的白底區塊 */<br />.plurk_box, .plurk_cnt_holder, .response_box, .plurk_body {<br />    background-color: #484848 !important;<br />    color: #eee !important;<br />}<br /><br />/* 回應輸入框 */<br />.response_input, .plurk_form textarea {<br />    background-color: #3a3a3a !important;<br />    color: #eee !important;<br />    border-color: #666 !important;<br />}<br /><br />/* 時間、小字等 */<br />.plurk_cnt .info, .plurk_cnt .qualifier, .plurk_cnt .td_cnt {<br />    color: #bbb !important;<br />}<br /><br />/* 河道回覆輸入框 */<br />#reply_box_holder, #reply, .reply_box {<br />    background-color: #3a3a3a !important;<br />    color: #eee !important;<br />}<br /><br />#reply textarea, #reply input, #reply_box_holder textarea {<br />    background-color: #444 !important;<br />    color: #eee !important;<br />    border-color: #666 !important;<br />}</pre>



<p>Tampermonkey Script </p>



<pre class="wp-block-preformatted">// ==UserScript==<br />// @name         Plurk Dark Theme<br />// @namespace    http://tampermonkey.net/<br />// @version      1.7<br />// @description  Plurk 全站暗色主題<br />// @match        https://www.plurk.com/*<br />// @run-at       document-idle<br />// ==/UserScript==<br /><br />(function() {<br />    'use strict';<br />    var css = '';<br />    css += 'html body .plurk_cnt, html body .plurk_cnt .text_holder { background-color: #484848 !important; color: #eee !important; }';<br />    css += 'html body .plurk_cnt a { color: #7ab8ff !important; }';<br />    css += 'html body a.ex_link, html body a.ex_link.meta { background: #555 !important; color: #ddd !important; border-color: #666 !important; }';<br />    css += 'html body a.ex_link *, html body a.ex_link.meta * { color: #ddd !important; }';<br />    css += 'html body .plurk_box, html body .plurk.bigplurk, html body .plurk.divplurk { background-color: #484848 !important; color: #eee !important; }';<br />    css += 'html body .display .plurk_cnt { background-color: #484848 !important; color: #eee !important; }';<br />    css += 'html body .response_box { background-color: #3a3a3a !important; color: #eee !important; }';<br />    css += 'html body .response_box .list-container { color: #eee !important; }';<br />    css += 'html body .plurk.response { color: #eee !important; }';<br />    css += 'html body .mini_form, html body .input_holder { background-color: #444 !important; color: #eee !important; border-color: #666 !important; }';<br />    css += 'html body textarea, html body textarea.content { background: #3a3a3a !important; color: #eee !important; border-color: #666 !important; }';<br />    css += 'html body .drop_indicator { background-color: #444 !important; color: #ccc !important; }';<br />    css += 'html body .pif-option.scroll-to-bottom { background-color: #444 !important; color: #ccc !important; }';<br />    css += 'html body .pop-view, html body .pop-window-view { background-color: #444 !important; color: #eee !important; }';<br />    css += 'html body .list .plurk_cnt { background-color: #505050 !important; color: #eee !important; }';<br />    css += 'html body .plurk_cnt .info, html body .plurk_cnt .qualifier { color: #bbb !important; }';<br />    css += 'html body #static-ads, html body .plurk-gpt-ad { background-color: transparent !important; }';<br /><br />    // hover - 只針對回應區，首噗不動<br />    css += 'html body .response_box .plurk.response:hover { background-color: #4a4a4a !important; color: #eee !important; }';<br />    css += 'html body .response_box .plurk.response:hover .plurk_cnt { background-color: #4a4a4a !important; color: #eee !important; }';<br /><br />    // 首噗 hover 鎖死不變<br />    css += 'html body .plurk.bigplurk:hover, html body .plurk.bigplurk:hover .plurk_cnt, html body .plurk.bigplurk:hover .text_holder { background-color: #484848 !important; color: #eee !important; }';<br /><br />    var style = document.createElement('style');<br />    style.textContent = css;<br />    document.head.appendChild(style);<br />})();</pre>



<p>dasd</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2026/04/02/6492/plurk-dark-mode/">Plurk Dark Mode</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2026/04/02/6492/plurk-dark-mode/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Taco Index</title>
		<link>https://richliu.com/2026/04/01/6489/taco-index/</link>
					<comments>https://richliu.com/2026/04/01/6489/taco-index/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Wed, 01 Apr 2026 00:31:57 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Claude Code]]></category>
		<category><![CDATA[Taco Index]]></category>
		<category><![CDATA[創意發想]]></category>
		<category><![CDATA[程式實作]]></category>
		<category><![CDATA[金融指數]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=6489</guid>

					<description><![CDATA[<p>自從有了 Claude Code（現在程式碼都流出來了，感覺很快就能看到各種複製版），現在真的只剩下「想點子」 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2026/04/01/6489/taco-index/">Taco Index</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>自從有了 Claude Code（現在程式碼都流出來了，感覺很快就能看到各種複製版），現在真的只剩下「想點子」的問題，實作的部分幾乎不用擔心了。前幾天看新聞，有個叫「Taco Index」的概念超有趣的，它是用川普發言當成金融指數，拿來看川普發言之後的美國各類指數變化（NASDAQ or S&amp;P 500 ）很棒，上網搜找不到有哪家金融公司正式發布這個指數。既然沒有現成的，那不如找 AI ！<br /><br />Claude Code 生出來的東西完全就是我想要的，甚至比我預想的還要準確。在 <a href="https://Taco.poorman.org" target="_blank" rel="noopener">Taco.poorman.org</a> 看到它。未來還會加上更多搞笑的指數吧，這些我以前想很久，也有弄出來，但是速度和品質真的比不上。</p>



<figure class="wp-block-image size-full"><img decoding="async" width="2147" height="1097" src="https://richliu.com/wp-content/uploads/2026/04/image.png" alt="" class="wp-image-6490" srcset="https://richliu.com/wp-content/uploads/2026/04/image.png 2147w, https://richliu.com/wp-content/uploads/2026/04/image-600x307.png 600w, https://richliu.com/wp-content/uploads/2026/04/image-768x392.png 768w, https://richliu.com/wp-content/uploads/2026/04/image-1536x785.png 1536w, https://richliu.com/wp-content/uploads/2026/04/image-2048x1046.png 2048w, https://richliu.com/wp-content/uploads/2026/04/image-816x417.png 816w" sizes="(max-width: 2147px) 100vw, 2147px" /></figure>
<p>The post <a rel="nofollow" href="https://richliu.com/2026/04/01/6489/taco-index/">Taco Index</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2026/04/01/6489/taco-index/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>使用純 Claude Code 開發 WordPress 外掛的心得</title>
		<link>https://richliu.com/2026/03/22/6482/%e4%bd%bf%e7%94%a8-claude-code-%e9%96%8b%e7%99%bc-wordpress-%e5%a4%96%e6%8e%9b%e7%9a%84%e5%bf%83%e5%be%97%e8%88%87-ai-%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e8%a7%80%e5%af%9f/</link>
					<comments>https://richliu.com/2026/03/22/6482/%e4%bd%bf%e7%94%a8-claude-code-%e9%96%8b%e7%99%bc-wordpress-%e5%a4%96%e6%8e%9b%e7%9a%84%e5%bf%83%e5%be%97%e8%88%87-ai-%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e8%a7%80%e5%af%9f/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Sun, 22 Mar 2026 06:23:35 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[隨手札記]]></category>
		<category><![CDATA[AI 工具]]></category>
		<category><![CDATA[AI 程式設計]]></category>
		<category><![CDATA[Claude Code]]></category>
		<category><![CDATA[WordPress 外掛]]></category>
		<category><![CDATA[程式開發]]></category>
		<category><![CDATA[軟體工程]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=6482</guid>

					<description><![CDATA[<p>作者認為AI處理語言（包括程式語言）有其優勢，並分享使用OpenClaw和Claude Code的經驗。他利用 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2026/03/22/6482/%e4%bd%bf%e7%94%a8-claude-code-%e9%96%8b%e7%99%bc-wordpress-%e5%a4%96%e6%8e%9b%e7%9a%84%e5%bf%83%e5%be%97%e8%88%87-ai-%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e8%a7%80%e5%af%9f/">使用純 Claude Code 開發 WordPress 外掛的心得</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img decoding="async" width="1706" height="519" src="https://richliu.com/wp-content/uploads/2026/03/image-2.png" alt="" class="wp-image-6484" srcset="https://richliu.com/wp-content/uploads/2026/03/image-2.png 1706w, https://richliu.com/wp-content/uploads/2026/03/image-2-600x183.png 600w, https://richliu.com/wp-content/uploads/2026/03/image-2-768x234.png 768w, https://richliu.com/wp-content/uploads/2026/03/image-2-1536x467.png 1536w, https://richliu.com/wp-content/uploads/2026/03/image-2-816x248.png 816w" sizes="(max-width: 1706px) 100vw, 1706px" /></figure>



<p>作者認為AI處理語言（包括程式語言）有其優勢，並分享使用<a href="https://openclaw.ai" target="_blank" rel="noopener">OpenClaw</a>和Claude Code的經驗。他利用Claude Code開發了兩款WordPress外掛：<a href="https://github.com/richliu/wp-ai-writing-assistant" target="_blank" rel="noopener">wp-ai-writing-assistant</a>用於AI校稿與分類，以及<a href="https://github.com/richliu/wp-ai-clipper" target="_blank" rel="noopener">wp-ai-clipper</a>瀏覽器擴充功能（仍在開發中）。心得包括AI產出穩定但偶有幻覺，適合解決明確問題，但大型任務容易出錯且耗費資源。他認為人類角色轉為PM與QA，而SaaS應發展基礎建設，客製化交由AI處理。最後鼓勵學習相關技能，並享受探索AI世界的過程。</p>



<p>註: 第一段是 DeepSeek 產生的，很明顯的就有錯誤，我沒有寫到 OpenClaw 的經驗，只是提到。</p>



<span id="more-6482"></span>



<p>我知道這個議題紅了很久，我不是網紅，也沒經營個人事業，所以沒有第一時間跳進去，這樣也有一個好處，慢一點進入市場才可以看得更清楚。就像 <a href="https://openclaw.ai" target="_blank" rel="noopener">OpenClaw</a> 這個也沒有必要太早進去，現在都在燒 tokens 的階段，少數人可能能用，但大多數可能都是看個熱鬧。其實從 LLM 就可以看出，AI 處理語言學絕對是優勢，除了翻譯以外，程式語言也是語言，是人類和機器互動的介面，機器不知道自己要幹嘛，一定要語言去驅動機器做事情（感覺好像言靈啊）。而最近接觸 Claude Code，我覺得這個服務非常成熟，成熟到嚇死我了，可以說是非常好用。</p>



<p>用 Claude Code 寫了兩支 WordPress 外掛 ，<strong>這中間我完全沒有動到任何程式碼</strong><br /><strong><a href="https://github.com/richliu/wp-ai-writing-assistant" target="_blank" rel="noopener">wp-ai-writing-assistant</a></strong>: 因為我要的功能很簡單，就是用 AI API 幫我校稿後加上 tag 分類，但目前在 WordPress 外掛中，有這個功能的都要收費，免費的並沒有相近的功能。所以想了一下，那就客製化我要的功能吧。經過許多輪的迭代，目前自己試用已經算滿意，該有的功能都有了。</p>



<p><a href="https://github.com/richliu/wp-ai-clipper" target="_blank" rel="noopener">wp-ai-clipper</a>: 這是一款 Firefox 和 Chrome 擴充功能，能將當前網頁的資料截取並發送到 WordPress 上。不過目前仍在機器開發階段，由於瀏覽器的限制較多，需要更多嘗試與除錯。目前主要的限制在於 tokens 的數量，快爆炸了。</p>



<p>開發到現在的心得是：
* 很多功能都需要非常多次的溝通，而且要對基本功能或架構有一定的概念。
* 目前 Claude Code 的產出相對穩定，幾乎都可以執行，但偶爾還是會碰到幻覺的情況。
* 解決特定目標非常好用，尤其是當功能或 BUG 的定義很明確時。
* 如果要產出較大的功能，AI 很可能會理解錯誤。
* 增加新功能的同時，往往也會引入許多 BUG，尤其是較大的改動或新功能。
* 超大型任務會直接掛掉。我使用的是 Sonnet，試了幾次，大概燒掉了 weekly 額度的 10%，然後就完全當在那邊沒有畫面。還沒改用 Opus，因為那東西燒 tokens 燒得更兇，等額度重置後再說吧。

很多人講的都沒有錯，人類已經變成 AI 的 QA 和 code reviewer（甚至連 reviewer 都稱不上）。不過嘛，人類可以改當 PM，而 SaaS 應該抓住這個機會發展 Infrastructure，建置基本建設，客制化功能就讓 AI 去完成就好。

原因很簡單，目前的 AI 當然可以做到這些事，但實際上，就算能用 AI 完成，中大型程式要如何切割、如何拆分，還是需要人類來完成。將巨型功能分成小塊，就像是資工領域的軟體工程。如果程式太大，不僅太燒錢，還不一定能得到想要的效果；此外，核心部分完全交給 AI 完成的風險也太高了。</p>



<p>Claude Code 在其他領域的表現也不錯，等我有空買到 Max 來玩多任務角色扮演。因為 AI 自動產生程式碼有很多潛在的問題，像是 QA 或安全等，這些其實可以用 AI 監督 AI，這個就等下一輪的計畫再來研究。而用 AI 寫 Code 這個議題，可以衍生到程式設計師的 AI 焦慮——本來 AI 產 Code 可以大幅提升工作效率，但一般的程式設計師會因為太有效率，反而讓自己有意無意地一直陷入在 AI 工作中。有些人會變得更興奮（像是我），所以反而變得更忙、更累，這就等我有空再來談這個問題吧（當然現在就懶得自己寫）。</p>



<p>結論：我認為每個人都應該學習，不過現階段確實還需要掌握更多其他技能；未來會如何發展也難以預料，我們都還在起步階段。就像我們現在開發客製化功能，但未來是否會出現專門協助客製化的工作，甚至連協助客製化都能由 AI 自動完成，這些都還是未知數。不過，對於有興趣探索未來的人來說，現在已經是一個不錯的切入點，Enjoy AI World。</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2026/03/22/6482/%e4%bd%bf%e7%94%a8-claude-code-%e9%96%8b%e7%99%bc-wordpress-%e5%a4%96%e6%8e%9b%e7%9a%84%e5%bf%83%e5%be%97%e8%88%87-ai-%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e8%a7%80%e5%af%9f/">使用純 Claude Code 開發 WordPress 外掛的心得</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2026/03/22/6482/%e4%bd%bf%e7%94%a8-claude-code-%e9%96%8b%e7%99%bc-wordpress-%e5%a4%96%e6%8e%9b%e7%9a%84%e5%bf%83%e5%be%97%e8%88%87-ai-%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e8%a7%80%e5%af%9f/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python mysql.connector.errors.DataError: 1366 (22007): Incorrect string value:</title>
		<link>https://richliu.com/2024/05/12/5973/python-mysql-connector-errors-dataerror-1366-22007-incorrect-string-value/</link>
					<comments>https://richliu.com/2024/05/12/5973/python-mysql-connector-errors-dataerror-1366-22007-incorrect-string-value/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Sun, 12 May 2024 08:55:58 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[MariaDB]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[UTF-8]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=5973</guid>

					<description><![CDATA[<p>After check all mysql (mariadb) setting, I realize that [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2024/05/12/5973/python-mysql-connector-errors-dataerror-1366-22007-incorrect-string-value/">Python mysql.connector.errors.DataError: 1366 (22007): Incorrect string value:</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>After check all mysql (mariadb) setting, I realize that should be client issue, it needs to add &#8220;chatset=&#8217;utf8mb4&#8242;&#8221; to mysql.connector.connect command. </p>



<pre class="wp-block-preformatted">mydb = mysql.connector.connect(
    host="IP or Host",
    user="&lt;user>",
    passwd="&lt;password>",
    database="&lt;yourDB>",
    # set charset to utf8mb4 to support emojis
    charset='utf8mb4'
)</pre>



<p>ref. https://stackoverflow.com/a/73648817/1371373</p>



<p></p>
<p>The post <a rel="nofollow" href="https://richliu.com/2024/05/12/5973/python-mysql-connector-errors-dataerror-1366-22007-incorrect-string-value/">Python mysql.connector.errors.DataError: 1366 (22007): Incorrect string value:</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2024/05/12/5973/python-mysql-connector-errors-dataerror-1366-22007-incorrect-string-value/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Ampere Altra Mt. Jade OpenBMC and EDKII build guide on ARM64 platform</title>
		<link>https://richliu.com/2022/06/23/4601/ampere-altra-mt-jade-openbmc-build-guide-on-arm64-platform/</link>
					<comments>https://richliu.com/2022/06/23/4601/ampere-altra-mt-jade-openbmc-build-guide-on-arm64-platform/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Thu, 23 Jun 2022 05:31:55 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[ARM]]></category>
		<category><![CDATA[Computer/Technical]]></category>
		<category><![CDATA[Embedded]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Altra]]></category>
		<category><![CDATA[Ampere Computing]]></category>
		<category><![CDATA[arm64]]></category>
		<category><![CDATA[EDKII]]></category>
		<category><![CDATA[OpenBMC]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=4601</guid>

					<description><![CDATA[<p>Ampere announce Altra CPU, it&#8217;s a 80 cores ARM64v [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2022/06/23/4601/ampere-altra-mt-jade-openbmc-build-guide-on-arm64-platform/">Ampere Altra Mt. Jade OpenBMC and EDKII build guide on ARM64 platform</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Ampere announce Altra CPU, it&#8217;s a 80 cores ARM64v8 CPU for cloud native workloads. Altra Max CPU is 128 cores. Follow the CPU, Ampere also has a CRB (customer reference board) named Mt. Jade, and Ampere also open source OpenBMC and EDKII source code for Mt. Jade platform. <br /><br />This article is personal note, all information can be found from internet. And open source project keeps going, it might be some minor differences when you find this article. </p>



<div class="wp-block-rank-math-toc-block" id="rank-math-toc"><h2>Table of Contents</h2><nav><ul><li><a href="#before-build-source-code">Before Build Source Code</a></li><li><a href="#prepare-build-environment">Prepare Build Environment</a><ul><li><a href="#get-the-ubuntu-18-04-cloud-image">Get the Ubuntu 18.04 cloud image</a></li><li><a href="#prepare-hostname-and-userdata-for-vm">Prepare hostname and userdata for VM</a></li></ul></li><li><a href="#build-mt-jade-edkii">Build Mt. Jade EDKII</a><ul><li><a href="#prepare-vm-environment">Prepare VM environment</a></li><li><a href="#get-build-environment">Get build environment</a></li><li><a href="#build-and-sign-the-image">Build and Sign the image</a></li><li><a href="#manual-build-edkii">Manual Build EDKII</a></li></ul></li><li><a href="#build-mt-jade-open-bmc">Build Mt. Jade OpenBMC</a></li><li><a href="#prepare-build-environment-1">Prepare build environment</a></li><li><a href="#build-open-bmc">Build OpenBMC</a></li><li><a href="#upgrade-firmware">Upgrade Firmware</a><ul><li><a href="#update-open-bmc-firmware">Update OpenBMC firmware</a><ul><li><a href="#update-via-url">Update via URL</a></li><li><a href="#update-via-ssh">Update via SSH</a></li></ul></li><li><a href="#update-uefi-firmware">Update UEFI firmware</a></li><li><a href="#update-scp-firmware">Update SCP firmware</a></li></ul></li><li><a href="#serial-console">Serial Console</a></li><li><a href="#reference">Reference</a></li><li><a href="#error-message">Error Message</a><ul><li><a href="#error-templateconf-value-which-is-nvme-openbmc-meta-ampere-meta-mitchell-must-point-to-meta-some-layer-conf-templates-template-name">Error: TEMPLATECONF value (which is /nvme/openbmc/meta-ampere/meta-mitchell) must point to meta-some-layer/conf/templates/template-name</a></li><li><a href="#initializing-oe-build-env">Initializing OE build env</a></li><li><a href="#">
</a></li></ul></li></ul></nav></div>



<span id="more-4601"></span>



<h2 class="wp-block-heading" id="before-build-source-code">Before Build Source Code</h2>



<p>This procedure runs on ARM64 platform, it should be also run on x86 platform, but I have not try it. <br /><br />Build environment : Ampere eMAG CPU (32 cores) with 256G DRAM and uses 64G/128G RAM to build code, sometime if it cannot finsih compile tasks, probably your DRAM is not sufficient to build the code, I tried 16G and it doesn;t work.<br /><br />Because host is running Ubuntu 22.04, and OpenBMC and EDKII only can be built on Ubuntu 18.04, so, it needs to use either virtual machine or contianer technologies to have Ubuntu 18.04 environment. <br /><br />This note uses qemu to prepare build environment, tried docker but it doesn&#8217;t work, probably I will re-try it someday. </p>



<p>If use NFS or qemu overlayers filesystem to bridge folders ourside into VM, it might cause build problem, so, please increase disk size for you virtual machine virtual disk size, use nfs or share folder for copy images or source code only. <br /><br />If want to build a workable EDKII code and run it on Ampere Mt. Jade platform, it needs to have Ampere fimware ATF and SCP binary, it might register Ampere customer connect to download those image files, without it, it only can build OpenBMC binary. </p>



<h2 class="wp-block-heading" id="prepare-build-environment">Prepare Build Environment </h2>



<h3 class="wp-block-heading" id="get-the-ubuntu-18-04-cloud-image">Get the Ubuntu 18.04 cloud image</h3>



<pre class="wp-block-preformatted">$ wget https://cloud-images.ubuntu.com/releases/bionic/release/ubuntu-18.04-server-cloudimg-arm64.img
$ sudo apt install qemu-efi</pre>



<h3 class="wp-block-heading" id="prepare-hostname-and-userdata-for-vm">Prepare hostname and userdata for VM</h3>



<p>it needs to prepare two files, meta-file and user-data, following is example for meta-file </p>



<pre class="wp-block-preformatted">instance-id: Image-openbmc
local-hostname: openbmc
</pre>



<p>user-data file, this example username is ubuntu, password is ubuntu</p>



<pre class="wp-block-preformatted">#cloud-config
password: ubuntu
chpasswd: { expire: False }
ssh_pwauth: True
ssh_authorized_keys:
  - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+Y/6m4XFeEGKqR2H7wbsUQUVWvB0gC/+CeJqfyvOX++SETKapFtI5CiidkyW/B1GQM4XUlmE9zPlCAcolPfMpXB0CNQQ5l0F5Z+FW6b4RVjFV/KEcQ7R3XkKRa0XhC6hKkNc5P95fNhXr8Do1bSEmd9mPIiOrFaUEZ9EReO+ZTsGsytFIuQV8rOZfQjClktXrqk3F6jJ+TV3THcVNpKvnLfps56Hc/j9jdiadLv91yuifz4lCMbv/D/0hMtf4KhN5tV//QRgUxEUeC7aPW6sKD2GMYMxc9UsSyRRQ9IFWjJMkgzKyuxgNKe7u4WjERFoxEUrmFK01UsrX+lRw9e9n user@hostname
</pre>



<p>Than, it can create a configure file for QEMU</p>



<pre class="wp-block-preformatted">$ cloud-localds -v cloudinit.img user-data meta-file</pre>



<p>Increase Ubuntu cloud image disk size, bigger is better, suggest more than 200G, minimal should be around 100G.</p>



<pre class="wp-block-preformatted">$ qemu-img resize ubuntu-18.04-server-cloudimg-arm64.img +200G</pre>



<p>Prepare UEFI BIOS and storage for booting</p>



<pre class="wp-block-preformatted">dd if=/dev/zero of=flash0.img bs=1M count=64
dd if=/usr/share/qemu-efi/QEMU_EFI.fd of=flash0.img conv=notrunc
dd if=/dev/zero of=flash1.img bs=1M count=64</pre>



<p>Running the VM script, it will also create a QEMU virtfs for file sharing, but do not use that folder to build code. How to access share folder, it can reference this article <a href="https://richliu.com/2017/09/25/2173/qemu-share-directory-with-host-without-networking/" target="_blank" rel="noreferrer noopener">QEMU Share Directory with Host Without Networking</a></p>



<p></p>



<pre class="wp-block-preformatted">IMAGE1=ubuntu-18.04-server-cloudimg-arm64.img
sudo qemu-system-aarch64 -name vm1 \
         -machine virt,gic_version=3,accel=kvm,usb=off \
         -cpu host -m 128G \
         -smp 32,sockets=1,cores=32,threads=1 \
         -nographic -nodefaults \
         -pflash flash0.img -pflash flash1.img \
         -drive file=$IMAGE1,if=none,id=disk1 \
         -device virtio-blk-device,drive=disk1 \
         -drive file=cloudinit.img,if=virtio,format=raw \
         -virtfs local,path=/nvme/obmc,mount_tag=host0,security_model=passthrough,id=host0 \
         -netdev tap,id=net0,ifname=tap0 \
         -device virtio-net-device,netdev=net0,mac=52:54:00:11:11:12 \
         -serial telnet::9001,server,nowait &gt; guest_log-1.txt 2&gt;&gt; guest_log-1.txt
</pre>



<h2 class="wp-block-heading" id="build-mt-jade-edkii">Build Mt. Jade EDKII</h2>



<h3 class="wp-block-heading" id="prepare-vm-environment">Prepare VM environment</h3>



<p>After login into VM, it needs to install software to compile EDKII. <br />Command to install basic packages. </p>



<pre class="wp-block-preformatted">sudo apt update 
sudo apt install -y git vim tmux lftp net-tools ethtool bc
sudo apt install -y \
  build-essential uuid-dev acpica-tools nasm \
  python3 python3-distutils python3-pip \
  gawk
sudo apt install -y libssl-dev gnu-efi
sudo apt install bison flex
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1</pre>



<p>Next step is follow this document to download Ampere EDKII source code  and setup enviroment. <br />https://github.com/AmpereComputing/edk2.git<br /><br />First, prepare build environment parameters, if VM reboot, it needs to re-run it. </p>



<pre class="wp-block-preformatted">export WORKSPACE=/nvme/tianocore<br />mkdir -p $WORKSPACE<br />cd $WORKSPACE<br /><s>export PACKAGES_PATH=$PWD/edk2:$PWD/edk2-platforms</s><br /># PACKAGES_PATH is default include path, sometimes miss package can include more directories here. <br /># if still cannot find some files, try to run submodules command on next step again. <br />export PACKAGES_PATH=$PWD/edk2:$PWD/edk2-platforms:$PWD/edk2-non-osi/:$PWD/edk2-platforms/Features/</pre>



<p>Chang into that folder, clone Ampere Computiner edk2 source code. </p>



<pre class="wp-block-preformatted">cd $WORKSPACE
git clone https://github.com/AmpereComputing/edk2.git
cd edk2
git submodule init &amp;&amp; git submodule update
cd ..
git clone https://github.com/AmpereComputing/edk2-platforms.git</pre>



<h3 class="wp-block-heading" id="get-build-environment">Get build environment</h3>



<p>This step is to build the basic tools.</p>



<pre class="wp-block-preformatted">cd $WORKSPACE
. edk2/edksetup.sh

# Build BaseTool, only need to run once 
make -C edk2/BaseTools </pre>



<p>After compiled the EDK2 basic tool, next step is to prepare edk2-platforms and edk2-ampere-tools <br /><br />edk2-ampere-tools has a very good build script, <br />it can help to build the EDK2 and also package ATF into together. <br />we will introduct it on following steps. </p>



<pre class="wp-block-preformatted">cd edk2-platforms
git checkout -b test remotes/origin/ampere

# make a link to library to fix some problem
ln -sf /nvme/tianocore/edk2-platforms/Features/Intel/OutOfBandManagement .
cd ..
git clone https://github.com/AmpereComputing/edk2-ampere-tools
</pre>



<h3 class="wp-block-heading" id="build-and-sign-the-image">Build and Sign the image</h3>



<p>Because current tree Atftool migrate to OpenSSL 3.0, and Ubuntu 18.04 still use OpenSSL 1.0x, <br />I choice to roll back to old version to support OpenSSL 1.0x, support it can build Atftool on Ubuntu 22.04 or compile OpenSSL 3.0 manually, I might try it later. </p>



<pre class="wp-block-preformatted">cd /nvme/tianocore 
mkdir -p AtfTools
cd AtfTools
git init
git remote add origin -f https://github.com/ARM-software/arm-trusted-firmware.git
git config core.sparseCheckout true

echo -ne "include/tools_share\nmake_helpers\ntools/cert_create\ntools/fiptool" &gt; .git/info/sparse-checkout

git -C . checkout --track origin/master
# Due to current AtfTool only support OpenSSL 3.0 , switch to previous version 
git checkout -b test b94bf967e62b23a376a5026de69d06a0e8d6bf78
make -C tools/cert_create CRTTOOL=cert_create
$ make -C tools/fiptool FIPTOOL=fiptool</pre>



<p>configure PATH to  fiptool and cert_create</p>



<pre class="wp-block-preformatted">cd /nvme/tianocore
export PATH=$PATH:$PWD/AtfTools/tools/cert_create:$PWD/AtfTools/tools/fiptool
</pre>



<p>This step is parepare Mt. Jade ATF and SCP binary for compile, it needs to get both binary file from <a href="https://connect.amperecomputing.com/" target="_blank" rel="noreferrer noopener">Ampere customer connect</a>. and also suggest to use the same version as OpenBMC/EDKII</p>



<pre class="wp-block-preformatted">cd $WORKSPACE
mv &lt;path to&gt;/altra_atf_signed_2.06.20220426.slim .
mv &lt;path to&gt;/altra_scp_signed_2.06.20220426.slim .
cd edk2-ampere-tools
./edk2-build.sh -b RELEASE Jade --atf-image $WORKSPACE/altra_atf_signed_2.06.20220426.slim --scp-image $WORKSPACE/altra_scp_signed_2.06.20220426.slim</pre>



<p>If everything is perfect, the binary code would be looks like below. </p>



<pre class="wp-block-preformatted">Results: /nvme/tianocore/edk2-ampere-tools/BUILDS/jade_tianocore_atf_2.06.100
total 45888
-rw------- 1 root   root       3343 Jun 15 12:40 dbukey.auth
-rw------- 1 root   root       2002 Jun 15 12:40 del_dbukey.auth
-rw-r--r-- 1 root   root       2008 Jun 15 12:38 jade_board_setting.bin
-rw-rw-r-- 1 ubuntu ubuntu    14532 Jun 15 04:08 jade_board_setting.txt
-rw-r--r-- 1 root   root     670845 Jun 15 12:40 jade_scp_2.06.100.cap
-rw-r--r-- 1 root   root     262144 Jun 15 12:40 jade_scp_2.06.100.dbu.sig.img
-rw-r--r-- 1 root   root    8126464 Jun 15 12:38 jade_tianocore_2.06.100.fd
-rw-r--r-- 1 root   root   14040229 Jun 15 12:40 jade_tianocore_atf_2.06.100.cap
-rw-r--r-- 1 root   root   13631488 Jun 15 12:40 jade_tianocore_atf_2.06.100.dbu.sig.img
-rw-r--r-- 1 root   root   10225352 Jun 15 12:38 jade_tianocore_atf_2.06.100.img
------------------------------------------------------------
                          Ampere Jade (AARCH64) RELEASE pass
------------------------------------------------------------
pass    1
fail    0</pre>



<p id="block-c791d1c4-9fd3-4983-bb20-21d321ee9683">It can use the jade_tianocore_atf_2.06.100.img for firmware update. </p>



<p>Note:  When latest time I compile the edkII binary, latest version will fail to build, it need to roll back to previous version. </p>



<h3 class="wp-block-heading" id="manual-build-edkii">Manual Build EDKII</h3>



<p>If still want to build EDKII manually, here is some command can help you. </p>



<pre class="wp-block-preformatted">cd edk2-platform
build -a AARCH64 -t GCC5 -b RELEASE -D SECURE_BOOT_ENABLE -p Platform/Ampere/JadePkg/Jade.dsc
or to use all CPU to compile the EDKII.
build -n `nproc` -a AARCH64 -t GCC5 -b RELEASE -D SECURE_BOOT_ENABLE -p Platform/Ampere/JadePkg/Jade.dsc</pre>



<p>the generated image on $WORKSPACE/Build/Jade/RELEASE_GCC5/FV/BL33_JADE_UEFI.fd,<br />for this case, on the /nvme/tianocore/Build/Jade/RELEASE_GCC5/FV/BL33_JADE_UEFI.fd</p>



<p>then, it needs to use ampere special tool to generate EDKII image with Ampere ATF image.</p>



<h2 class="wp-block-heading" id="build-mt-jade-open-bmc">Build Mt. Jade OpenBMC</h2>



<h2 class="wp-block-heading" id="prepare-build-environment-1">Prepare build environment</h2>



<p>Before build OpenBMC, it needs to install necessary packages, <br />it can build both OpenBMC and EDKII on the same VM, or it can build it on different VM. <br /><br />Following is necessary packages for OpenBMC.</p>



<pre class="wp-block-preformatted">$ sudo apt-get install -yy \
     build-essential \
     chrpath \
     cpio \
     debianutils \
     diffstat \
     gawk \
     git \
     iputils-ping \
     libdata-dumper-simple-perl \
     liblz4-tool \
     libsdl1.2-dev \
     libthread-queue-any-perl \
     locales \
     python \
     python3 \
     socat \
     subversion \
     texinfo \
     wget \
     zstd</pre>



<p>Download Open BMC source code and OpenBMC build script. </p>



<pre class="wp-block-preformatted">$ cd /nvme
$ git clone https://github.com/ampere-openbmc/openbmc.git
$ git clone https://github.com/openbmc/openbmc-build-scripts.git
</pre>



<p>modify openbmc-build-scripts/build-setup.sh around line #140, <br />replace &#8220;Clone in openbmc master to ${obmc_dir}&#8221; to https://github.com/ampere-openbmc/openbmc.git<br /><br />it can download right source code. </p>



<pre class="wp-block-preformatted">git clone ${branch} https://github.com/ampere-openbmc/openbmc.git</pre>



<p>If you use more than 32 cores to build the source code, it might cause compile fail because some compile tool might have problem on build code on ARM64 massive code. A easy way to check that is run dmesg to check whether Linux kernel has OOM killer on some package compile fail message like nodejs.<br /><br />Limited CPU number to 32 , modify openbmc-build-scripts/build-setup.sh, on line 84. </p>



<pre class="wp-block-preformatted"> 84 # num_cpu=${num_cpu:-$(nproc)}
 85 num_cpu=32
</pre>



<h2 class="wp-block-heading" id="build-open-bmc">Build OpenBMC</h2>



<p>This step is to prepare test build environment </p>



<pre class="wp-block-preformatted">$ cd /nvme
$ target=mtjade WORKSPACE=/nvme/openbmc branch="--branch ampere --single-branch" ./openbmc-build-scripts/build-setup.sh</pre>



<p>Setup openbmc machine type to mt. Jade and compile OpenBMC. </p>



<pre class="wp-block-preformatted">$ <s>export TEMPLATECONF=meta-ampere/meta-jade</s>
$ export TEMPLATECONF=meta-ampere/meta-jade/conf/templates/default/
$ export TMPDIR=/nvme/temp
$ export LC_ALL=en_US.UTF-8

$ cd /nvme/openbmc
$ . openbmc-env
$ cd ..
$ source ./setup mtjade
$ bitbake obmc-phosphor-image
</pre>



<p>if system it mt.mitchell</p>



<pre class="wp-block-preformatted">$ export TEMPLATECONF=meta-ampere/meta-mitchell/conf/templates/default/
$ export TMPDIR=/nvme/temp
$ export LC_ALL=en_US.UTF-8

$ cd /nvme/openbmc
$ . openbmc-env
$ cd ..
$ source ./setup mtmitchell-dcscm
$ bitbake obmc-phosphor-image</pre>



<p>When compile, there is an openocd compile error, it cannot access to original website probably caused by the website was down. Temperory solutoin is to remove the package. <br />modify file meta-ampere/meta-common/recipes-ac01/packagegroups/packagegroup-ampere-apps.bb, find openocd and delete it, down. </p>



<p>When finish compile, the binary will locate on tmp/deploy/images/mtjade/, absoult path is /nvme/openbmc/build/mtjade/tmp/deploy/images/mtjade/<br /><br />ex: (only list partical files)</p>



<pre class="wp-block-preformatted">obmc-phosphor-image-mtjade-20220616040212.rootfs.manifest
obmc-phosphor-image-mtjade-20220616040212.rootfs.squashfs-xz
obmc-phosphor-image-mtjade-20220616040212.static.mtd
obmc-phosphor-image-mtjade-20220616040212.static.mtd.all.tar
obmc-phosphor-image-mtjade-20220616040212.static.mtd.tar
obmc-phosphor-image-mtjade-20220616040212.testdata.json
obmc-phosphor-image-mtjade.jffs2
obmc-phosphor-initramfs-mtjade-20220616004506.rootfs.cpio.xz
obmc-phosphor-initramfs-mtjade-20220616004506.rootfs.manifest
obmc-phosphor-initramfs-mtjade-20220616004506.testdata.json
</pre>



<p>obmc-phosphor-image-mtjade-20220616040212.static.mtd.tar is firmware file, it contain both obmc-phosphor-image-mtjade-20220616040212.static.mtd and obmc-phosphor-image-mtjade-20220616040212.rootfs.manifest files, and can be used for next step : firmware update.</p>



<h2 class="wp-block-heading" id="upgrade-firmware">Upgrade Firmware</h2>



<p><strong><span class="has-inline-color has-luminous-vivid-orange-color">*Notice: Update flash will take your own risk, especially physical damage your hardware.. </span></strong> <br /><br />If Mt. Jade is using AMI bios, suggest to use flash burner to update the OpenBMC firmware. <br />What I am using is GZU EZP XPro , it&#8217;s very cheap, only needs around US$30.- (please also purchase the SPI flash socket). <br /><br />This step need to un-plug BMC flash from Mt. Jade motherboard, please remeber the flash pin 1 location, it needs to follow the original position and put it back to socket. If you miss you will broken it. <br /></p>



<h3 class="wp-block-heading" id="update-open-bmc-firmware">Update OpenBMC firmware</h3>



<p>ref. <a href="https://github.com/openbmc/docs/blob/master/architecture/code-update/code-update.md" target="_blank" rel="noopener">OpenBMC Code Update</a></p>



<h4 class="wp-block-heading" id="update-via-url">Update via URL</h4>



<p>Suppose that it already has OpenBMC firmware, it can use software to upgrade firmware ,<br />first step is to get web token, then use this token on next step to upgrade firmware. <br /><br />Following is a simple script to upgrade flash, it can be integrated into your script. </p>



<pre class="wp-block-preformatted">export BMC_IP=192.168.1.190
export FWFILE=obmc-phosphor-image-mtjade-20220616040212.static.mtd.tar

export token=`curl -k -H "Content-Type: application/json" -X POST https://${BMC_IP}/login -d '{"username" :  "root", "password" :  "0penBmc"}' | grep token | awk '{print $2;}' | tr -d '"'`

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    84  100    37  100    47    116    147 --:--:-- --:--:-- --:--:--   264


curl -k -H "X-Auth-Token: $token" \
       -H "Content-Type: application/octet-stream" \
       -X POST -T ${FWFILE} \
        https://${BMC_IP}/redfish/v1/UpdateService

{
  "@odata.id": "/redfish/v1/TaskService/Tasks/1",
  "@odata.type": "#Task.v1_4_3.Task",
  "Id": "1",
  "TaskState": "Running",
  "TaskStatus": "OK"
}</pre>



<p>If  conosle doesn&#8217;t not update and reboot, please use console login the OpenBMC and run &#8220;reboot&#8221; manually. <br />It will show message like below on OpenBMC console. </p>



<pre class="wp-block-preformatted">Updating kernel...
Erasing block: 69/69 (100%)
Writing kb: 4397/4397 (100%)
Verifying kb: 4397/4397 (100%)
Updating rofs...
Erasing block: 366/366 (100%)
Writing kb: 11580/23376 (49%)
</pre>



<h4 class="wp-block-heading" id="update-via-ssh">Update via SSH</h4>



<p>Just update firmware (ex: obmc-phosphor-image-mtjade-20220616040212.static.mtd.tar) to BMC&#8217;s directory /tmp/images , it will shows a hash number like /tmp/images/d6718c8f, then run the following command</p>



<pre class="wp-block-preformatted">busctl set-property xyz.openbmc_project.Software.BMC.Updater \<br />  /xyz/openbmc_project/software/d6718c8f \<br />  xyz.openbmc_project.Software.Activation RequestedActivation s \<br />  xyz.openbmc_project.Software.Activation.RequestedActivations.Active</pre>



<h3 class="wp-block-heading" id="update-uefi-firmware">Update UEFI firmware </h3>



<p>Upgrade UEFI firmware<br />it needs to pack the UEFI image first , and it need to create MANIFEST file, looks like this </p>



<pre class="wp-block-preformatted">VER_purpose=xyz.openbmc_project.Software.Version.VersionPurpose.Host
version=jade_tianocore_atf_2.06.100
KeyType=OpenBMC
HashType=RSA-SHA256
MachineName=mtjade
</pre>



<p>make image file and MINIFEST file into the same file</p>



<pre class="wp-block-preformatted">$ tar -cvf jade_tianocore_atf_2.06.100.tar jade_tianocore_atf_2.06.100.img MANIFEST </pre>



<p>Run command below to upgrade UEFI firmware</p>



<pre class="wp-block-preformatted">export BMC_IP=192.168.1.190

export FWFILE=jade_tianocore_atf_2.06.100.tar

export token=`curl -k -H "Content-Type: application/json" -X POST https://${BMC_IP}/login -d '{"username" :  "root", "password" :  "0penBmc"}' | grep token | awk '{print $2;}' | tr -d '"'`

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    84  100    37  100    47    116    147 --:--:-- --:--:-- --:--:--   264


curl -k -H "X-Auth-Token: $token" \
       -H "Content-Type: application/octet-stream" \
       -X POST -T ${FWFILE} \
        https://${BMC_IP}/redfish/v1/UpdateService

</pre>



<p>Like OpenBMC, if it doesn&#8217;t update, just reboot to update it. <br />if stiall not work, try to upgrade it manually, yes, when I wrote this article, update via redfish doesn&#8217;t work, so, just copy it from github.</p>



<pre class="wp-block-preformatted"># on HOST
$ scp jade_tianocore_atf_2.06.100.tar root@192.168.1.190:/tmp

# on Target 
$ cd /tmp/images
$ mkdir fw
$ cd fw
$ tar xvf /tmp/jade_tianocore_atf_2.06.100.tar
$ firmware_update.sh /tmp/images/fw
--- Current Chassis State: On
--- Turning the Chassis off
--- Switch the host SPI bus to BMC.
Run update Primary Host SPI-NOR
--- Bind the ASpeed SMC driver
--- Locking power control
--- Flashing firmware to @/dev/mtd13
Erasing block: 157/157 (100%)
Writing kb: 9985/9985 (100%)
Verifying kb: 9985/9985 (100%)
--- Unlocking power control
--- Switch back to the primary Host SPI-NOR.
Turn on the Host
</pre>



<h3 class="wp-block-heading" id="update-scp-firmware">Update SCP firmware</h3>



<p>It needs to use sftp to transfer SCP firmware to target. <br />Following is example to upgrade SCP firmware.</p>



<pre class="wp-block-preformatted">On host
$ scp altra_scp_signed_2.06.20220426.slim root@192.168.1.190:/tmp

On OpenBMC side
$ ampere_firmware_upgrade.sh smpmpro /tmp/altra_scp_signed_2.06.20220426.slim</pre>



<p>After upgrade BIOS and SCP, if got any problem, suggest to reset bmc </p>



<pre class="wp-block-preformatted">$ ipmitool -U root -P 0penBmc -I lanplus -C 17 -H 192.168.2.18 mc reset cold</pre>



<h2 class="wp-block-heading" id="serial-console">Serial Console</h2>



<p>it can use command to get system CPU console.</p>



<pre class="wp-block-preformatted"># CPU console 
$ ssh root@192.168.190 -p 2200 
</pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1124" height="739" src="https://richliu.com/wp-content/uploads/2022/06/image.png" alt="" class="wp-image-4631" srcset="https://richliu.com/wp-content/uploads/2022/06/image.png 1124w, https://richliu.com/wp-content/uploads/2022/06/image-600x394.png 600w, https://richliu.com/wp-content/uploads/2022/06/image-768x505.png 768w" sizes="auto, (max-width: 1124px) 100vw, 1124px" /></figure>



<h2 class="wp-block-heading" id="reference">Reference</h2>



<p><a href="https://github.com/ampere-openbmc/openbmc" target="_blank" rel="noreferrer noopener">Ampere OpenBMC github</a><br /><a href="https://github.com/AmpereComputing/edk2-ampere-tools" target="_blank" rel="noreferrer noopener">EDK2 Ampere Tool</a><br /><a href="https://github.com/AmpereComputing/edk2" target="_blank" rel="noreferrer noopener">Ampere EDK2</a><br /><a href="https://github.com/AmpereComputing" target="_blank" rel="noreferrer noopener">Ampere Computing Github</a></p>



<h2 class="wp-block-heading" id="error-message">Error Message </h2>



<h3 class="wp-block-heading" id="error-templateconf-value-which-is-nvme-openbmc-meta-ampere-meta-mitchell-must-point-to-meta-some-layer-conf-templates-template-name">Error: TEMPLATECONF value (which is /nvme/openbmc/meta-ampere/meta-mitchell) must point to meta-some-layer/conf/templates/template-name</h3>



<p>Error message </p>



<h3 class="wp-block-heading" id="initializing-oe-build-env">Initializing OE build env</h3>



<pre class="wp-block-preformatted">Error: TEMPLATECONF value (which is /nvme/openbmc/meta-ampere/meta-mitchell) must point to meta-some-layer/conf/templates/template-name</pre>



<p>This is because followed the old configuration, it needs to point to right folder like</p>



<pre class="wp-block-preformatted">export TEMPLATECONF=meta-ampere/meta-jade/conf/templates/default/
. openbmc-env</pre>



<p>.</p>



<h3 class="wp-block-heading"><br /></h3>
<p>The post <a rel="nofollow" href="https://richliu.com/2022/06/23/4601/ampere-altra-mt-jade-openbmc-build-guide-on-arm64-platform/">Ampere Altra Mt. Jade OpenBMC and EDKII build guide on ARM64 platform</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2022/06/23/4601/ampere-altra-mt-jade-openbmc-build-guide-on-arm64-platform/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Python 取得 PM2.5 和天氣資訊</title>
		<link>https://richliu.com/2019/10/17/4192/python-%e5%8f%96%e5%be%97-pm2-5-%e5%92%8c%e5%a4%a9%e6%b0%a3%e8%b3%87%e8%a8%8a/</link>
					<comments>https://richliu.com/2019/10/17/4192/python-%e5%8f%96%e5%be%97-pm2-5-%e5%92%8c%e5%a4%a9%e6%b0%a3%e8%b3%87%e8%a8%8a/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Thu, 17 Oct 2019 15:16:41 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=4192</guid>

					<description><![CDATA[<p>最近終於將很久之前就說要架的室內 PM 2.5 偵測弄起來，上一版是用 Cacti 做的，但是有點過時了，這一 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2019/10/17/4192/python-%e5%8f%96%e5%be%97-pm2-5-%e5%92%8c%e5%a4%a9%e6%b0%a3%e8%b3%87%e8%a8%8a/">Python 取得 PM2.5 和天氣資訊</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="alignright is-resized"><img loading="lazy" decoding="async" src="https://richliu.com/wp-content/uploads/2019/10/image-1024x702.png" alt="" class="wp-image-4193" width="240" height="164" srcset="https://richliu.com/wp-content/uploads/2019/10/image-1024x702.png 1024w, https://richliu.com/wp-content/uploads/2019/10/image-300x206.png 300w, https://richliu.com/wp-content/uploads/2019/10/image-768x526.png 768w, https://richliu.com/wp-content/uploads/2019/10/image.png 1509w" sizes="auto, (max-width: 240px) 100vw, 240px" /></figure></div>



<p>最近終於將很久之前就說要架的室內 PM 2.5 偵測弄起來，上一版是用 Cacti 做的，但是有點過時了，這一版是用 Grafana + Prometheus 做的，看起來就漂亮多了<br /><br />不過架上去之後的問題是，想比較數值，但是又不想再組一套系統出來，畢竟感測器也是成本，不如就用現成的氣象和環保局的數據吧，反正都只是參考用的，看個大概就好了<br /></p>



<span id="more-4192"></span>



<h4 class="wp-block-heading">PM 2.5 的數據</h4>



<p>這是取用 <a rel="noreferrer noopener" aria-label="PM 2.5 Open Data  (opens in a new tab)" href="https://pm25.lass-net.org/" target="_blank">PM 2.5 Open Data </a>網站的數據，看起來是中研院架的，但是不知道為什麼是在 .org 下，不過沒關係，其中有提供很多來源，我自己是取用環保局的資料<br /><br />環保局的資料有一個問題，並不是每個地方都有，所以我是選用土城的測站，因為離家最近<br /><br />Open Data 的資料是 .gz ，不需要認證，所以用 urlopen 下載下來送到 gzip module 最後給 json 就可以解了，程式如下<br /><br />這個數據是每 10 分鐘更新一次，所以每 10 分鐘抓一次即可</p>



<pre class="wp-block-preformatted">def getpm25():
     req = Request(PM25URL)
     req.add_header('Accept-Encoding','gzip')
     response = urlopen(req)
     content = gzip.decompress(response.read())
     my_object = json.loads(content.decode('utf-8'))
     item = my_object['feeds'] 
     for i in range(len(item)):     
         # print(item[i]['County'])     
         if item[i]['SiteName'] == "土城":         
            print(item[i])         
            print("PM25:", item[i]['PM2_5'])         
            print("PM10:", item[i]['PM10'])</pre>



<h4 class="wp-block-heading">天氣的數據</h4>



<p>天氣的數據是取用中央氣象局的，目前 Google 到的資料也略有出入，所以我就寫個簡單的 Code 解出我要的資訊，應該可以更漂亮的解法，不過寫個 Sample 省大家時間也不錯<br /><br />氣象局的資料要去氣象資料開放平台註冊，註冊完會給一組 API ，再利用這組 API Key 抓你要的資料，我這邊選用的是 JSON 格式<br />O-A0001-001 ：資料型態，我這是即時氣象資料<br />Authorization=CWB-111111E2-1877-4711-2624-216276053413: API Key ，後面 KEY 要換成自己申請的<br />format=JSON，資料格式，還有其他的，但是我只有試 JSON<br /><br />if localitem[j][&#8216;elementName&#8217;] == &#8220;TEMP&#8221;:　>  氣溫<br />elif localitem[j][&#8216;elementName&#8217;] == &#8220;HUMD&#8221;: > 濕度<br /><br />說明文件可以參考 <a rel="noreferrer noopener" aria-label="中央氣象局開放資料平臺之資料擷取API (opens in a new tab)" href="https://opendata.cwb.gov.tw/dist/opendata-swagger.html" target="_blank">中央氣象局開放資料平臺之資料擷取API</a> ，有比較詳細的說明<br /></p>



<pre class="wp-block-preformatted">def get_local_temperature():
     res = "https://opendata.cwb.gov.tw/fileapi/v1/opendataapi/O-A0001-001?Authorization=CWB-111111E2-1877-4711-2624-216276053413&amp;format=JSON"
     with urllib.request.urlopen(res) as url:
         data = url.read()
         my_object = json.loads(data.decode('utf-8'))
         item = my_object['cwbopendata']['location']
         # print(item)
         for i in range(len(item)):
             # print(item[i])
             if item[i]['locationName'] == "鶯歌":
                 # print(item[i])             
                 # print(item[i]['weatherElement'])             
                 localitem = item[i]['weatherElement']             
                 for j in range(len(localitem)):                 
                     # print(localitem[j])                 
                     if localitem[j]['elementName'] == "TEMP":
                         print("Temp:", localitem[j]['elementValue']['value'])                 
                     elif localitem[j]['elementName'] == "HUMD":
                         print("RH:", localitem[j]['elementValue']['value'])</pre>



<p></p>
<p>The post <a rel="nofollow" href="https://richliu.com/2019/10/17/4192/python-%e5%8f%96%e5%be%97-pm2-5-%e5%92%8c%e5%a4%a9%e6%b0%a3%e8%b3%87%e8%a8%8a/">Python 取得 PM2.5 和天氣資訊</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2019/10/17/4192/python-%e5%8f%96%e5%be%97-pm2-5-%e5%92%8c%e5%a4%a9%e6%b0%a3%e8%b3%87%e8%a8%8a/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>PyCharm 內執行 QT Designer 和 ui 轉 py</title>
		<link>https://richliu.com/2019/02/21/3879/pycharm-%e5%85%a7%e5%9f%b7%e8%a1%8c-qt-designer-%e5%92%8c-ui-%e8%bd%89-py/</link>
					<comments>https://richliu.com/2019/02/21/3879/pycharm-%e5%85%a7%e5%9f%b7%e8%a1%8c-qt-designer-%e5%92%8c-ui-%e8%bd%89-py/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Thu, 21 Feb 2019 15:10:11 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[PyCharm]]></category>
		<category><![CDATA[PyQT]]></category>
		<category><![CDATA[PyQT5]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[QT]]></category>
		<category><![CDATA[QT Creator]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=3879</guid>

					<description><![CDATA[<p>看了幾篇文章都有些疏漏，並沒有辦法真正的做到直接在程式內直接呼叫 External tool 做到這兩件事 都 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2019/02/21/3879/pycharm-%e5%85%a7%e5%9f%b7%e8%a1%8c-qt-designer-%e5%92%8c-ui-%e8%bd%89-py/">PyCharm 內執行 QT Designer 和 ui 轉 py</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>看了幾篇文章都有些疏漏，並沒有辦法真正的做到直接在程式內直接呼叫 External tool 做到這兩件事<br /><br />都會有一些錯誤訊息</p>



<span id="more-3879"></span>



<p>我的環境是 Ubuntu 18.04 ，用 snap 安裝的 PyCharm <br />順便安裝 QT 相關的環境</p>



<pre class="wp-block-code"><code>$ sudo snap install pycharm-community --classic
$ sudo sudo apt install  pyqt5-dev-tools python3-pyqt5 qttools5-dev-tools</code></pre>



<p>到 File -&gt; Settings -&gt; Tools -&gt; External Tools 新增一個新的設定<br />先叫 PyUIC 吧</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh6.googleusercontent.com/prjTsGWULvFAiBAjwqep2eUeuyGoKUyCXEcg6ilIuWb6s25SQEaXSEG597UumOzY3M9kZHOE8-ZVw-U6Zv8ATEHJkptQD7-dxNwgLUcmwJ8T9NlMv-Wih1xi3sdwO6s-wtJ0Okp0" alt=""/><figcaption>我都加好了</figcaption></figure>



<p>設定如下<br />Program : /usr/bin/pyuic5<br />Arguments :  $FileName$ -o $FileNameWithoutExtension$.py <br />Working Directory  : $ProjectFileDir$/$FileDirRelativeToProjectRoot$</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="697" height="760" src="https://richliu.com/wp-content/uploads/2020/07/image.png" alt="" class="wp-image-4302" srcset="https://richliu.com/wp-content/uploads/2020/07/image.png 697w, https://richliu.com/wp-content/uploads/2020/07/image-275x300.png 275w" sizes="auto, (max-width: 697px) 100vw, 697px" /></figure>



<p>接下來再新增一個，就叫 QT Designer <br /><br />Program : /usr/lib/x86_64-linux-gnu/qt5/bin/designer<br />Arguments :  $FileName$ <br />Working Directory : $ProjectFileDir$/$FileDirRelativeToProjectRoot$</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="692" height="763" src="https://richliu.com/wp-content/uploads/2020/07/image-1.png" alt="" class="wp-image-4303" srcset="https://richliu.com/wp-content/uploads/2020/07/image-1.png 692w, https://richliu.com/wp-content/uploads/2020/07/image-1-272x300.png 272w" sizes="auto, (max-width: 692px) 100vw, 692px" /></figure>



<p>這樣就可以在目錄下的 .ui 檔案上選 PyUIC 將 .ui 轉成 .py <br />然後選 QT Designer 修改 .ui 檔<br /><br />你看這樣很簡單吧</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2019/02/21/3879/pycharm-%e5%85%a7%e5%9f%b7%e8%a1%8c-qt-designer-%e5%92%8c-ui-%e8%bd%89-py/">PyCharm 內執行 QT Designer 和 ui 轉 py</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2019/02/21/3879/pycharm-%e5%85%a7%e5%9f%b7%e8%a1%8c-qt-designer-%e5%92%8c-ui-%e8%bd%89-py/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>RSS Toeplitz Hash Calculation C Code</title>
		<link>https://richliu.com/2018/06/11/2288/rss-hash-calculation-c-code/</link>
					<comments>https://richliu.com/2018/06/11/2288/rss-hash-calculation-c-code/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Mon, 11 Jun 2018 13:32:05 +0000</pubDate>
				<category><![CDATA[Network]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[RSS]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=2288</guid>

					<description><![CDATA[<p>Toeplitz RSS(Receive Side Scaling) sample code 如下, 從 OD [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2018/06/11/2288/rss-hash-calculation-c-code/">RSS Toeplitz Hash Calculation C Code</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Toeplitz RSS(Receive Side Scaling) sample code 如下, 從 ODP Code 借來的</p>
<p>因為是測試用 code, 所以也不要太在乎語法什麼的<br />
輸出可以正確的跑出 microsoft 網站的 sample</p>
<pre lang="bash">$ ./a.out
sip: 187.149.9.66   dip:80.100.142.161 sport:1766   dport:2794   hash: 51ccc178
</pre>
<p>目前的 code 會計算 4 個 IP<br />
像是這樣</p>
<pre lang="bash">$ ./a.out
sip: 192.168.1.100  dip:10.0.0.100     sport:1000   dport:1000   hash: 8c2cb4f
sip: 193.168.1.100  dip:10.0.0.100     sport:1000   dport:1000   hash: ef1317e8
sip: 194.168.1.100  dip:10.0.0.100     sport:1000   dport:1000   hash: 5f061160
sip: 195.168.1.100  dip:10.0.0.100     sport:1000   dport:1000   hash: 2324d4ee
</pre>
<p>連檔名都叫 a.out 我真懶</p>
<p><code></code></p>
<p>#include &lt;stdint.h&gt;<br />
#include &lt;stdio.h&gt;<br />
#include &lt;endian.h&gt;<br />
#include &lt;string.h&gt;<br />
#include &lt;arpa/inet.h&gt;</p>
<p>/** rss data type */<br />
typedef union {<br />
uint8_t u8[40];<br />
uint32_t u32[10];<br />
} rss_key;</p>
<p>/** IPv4 tuple<br />
*<br />
*/<br />
typedef struct thash_ipv4_tuple {<br />
uint32_t src_addr;<br />
uint32_t dst_addr;<br />
union {<br />
struct {<br />
uint16_t sport;<br />
uint16_t dport;<br />
};<br />
uint32_t sctp_tag;<br />
};<br />
} thash_ipv4_tuple_t;</p>
<p>/** Thash tuple union */<br />
typedef union {<br />
thash_ipv4_tuple_t v4;<br />
//thash_ipv6_tuple_t v6;<br />
} thash_tuple_t;<br />
static const rss_key default_rss = {<br />
.u8 = {<br />
0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,<br />
0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,<br />
0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,<br />
0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,<br />
0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa,<br />
}<br />
};</p>
<p>static inline<br />
uint32_t thash_softrss(uint32_t *tuple, uint8_t len,<br />
const rss_key key)<br />
{<br />
uint32_t i, j, ret = 0;</p>
<p>for (j = 0; j &lt; len; j++) {<br />
for (i = 0; i &lt; 32; i++) {<br />
if (tuple[j] &amp; (1 &lt;&lt; (31 &#8211; i))) {<br />
ret ^= htobe32(((const uint32_t *)<br />
key.u32)[j]) &lt;&lt; i | (uint32_t)((uint64_t) (htobe32(((const uint32_t *)key.u32) [j + 1])) &gt;&gt; (32 &#8211; i));<br />
}<br />
}<br />
}</p>
<p>return ret;<br />
}<br />
int main(int argc,char *argv[]){<br />
thash_tuple_t tuple;<br />
uint32_t hash;<br />
uint32_t tuple_len;<br />
struct in_addr ip_addr_s,ip_addr_d;<br />
char str_s[15], str_d[15];</p>
<p>#if 0<br />
tuple.v4.src_addr = (uint32_t) inet_addr(&#8220;66.9.149.187&#8221;);<br />
tuple.v4.dst_addr = (uint32_t) inet_addr(&#8220;161.142.100.80&#8221;);<br />
ip_addr_s.s_addr = tuple.v4.src_addr;<br />
ip_addr_d.s_addr = tuple.v4.dst_addr;<br />
tuple_len += 2;<br />
tuple.v4.sport = htobe16(2794);<br />
tuple.v4.dport = htobe16(1766);<br />
tuple_len += 1;<br />
#endif</p>
<p>for(int i=0;i&lt;4;i++){<br />
tuple_len = 0;<br />
hash = 0;</p>
<p>tuple.v4.src_addr = (uint32_t) inet_addr(&#8220;192.168.1.100&#8221;);<br />
tuple.v4.src_addr = be32toh(tuple.v4.src_addr);<br />
tuple.v4.src_addr=tuple.v4.src_addr+i*4;<br />
tuple.v4.src_addr = htobe32(tuple.v4.src_addr);<br />
tuple.v4.dst_addr = (uint32_t) inet_addr(&#8220;10.0.0.100&#8221;);<br />
ip_addr_s.s_addr = tuple.v4.src_addr;<br />
ip_addr_d.s_addr = tuple.v4.dst_addr;<br />
tuple_len += 2;<br />
tuple.v4.sport = htobe16(1000);<br />
tuple.v4.dport = htobe16(1000);<br />
tuple_len += 1;</p>
<p>if (tuple_len){<br />
tuple.v4.src_addr = be32toh(tuple.v4.src_addr);<br />
tuple.v4.dst_addr = be32toh(tuple.v4.dst_addr);<br />
tuple.v4.sctp_tag = be32toh(tuple.v4.sctp_tag);<br />
hash = thash_softrss((uint32_t *)&amp;tuple,<br />
tuple_len, default_rss);<br />
}</p>
<p>ip_addr_s.s_addr = htobe32(tuple.v4.src_addr);<br />
ip_addr_d.s_addr = htobe32(tuple.v4.dst_addr);<br />
strcpy(str_s,inet_ntoa(ip_addr_s));<br />
strcpy(str_d,inet_ntoa(ip_addr_d));<br />
printf(&#8220;sip: %-14s dip:%-14s sport:%-6d dport:%-6d hash: %x \n&#8221;,<br />
str_s,str_d,<br />
tuple.v4.sport,<br />
tuple.v4.dport, hash);</p>
<p>}</p>
<p>return hash;<br />
}</p>
<p>附帶一提, 如果在 Linux 下要修改 hash key . 可以用 ethtool 這個指令, ex:</p>
<pre lang="bash">
$ ethtool -X enp5s0f4 hkey 6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a:6d:5a
</pre>
<p>ref.<br />
<a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/network/verifying-the-rss-hash-calculation" rel="noopener" target="_blank">Verifying the RSS Hash Calculation</a> : 可以比對計算出是不是正確<br />
<a href="http://www.ran-lifshitz.com/2014/08/28/symmetric-rss-receive-side-scaling/" rel="noopener" target="_blank">Symmetric RSS</a> : 有趣的文章, 提到原來的功能沒有辦法有效的 hash , 將所有的 key 都改 0x6d5a 就可以<br />
<a href="https://pdfs.semanticscholar.org/38b6/47c56a74d634d7c23fe0b99ea1eb6347b09e.pdf" rel="noopener" target="_blank">Scalable TCP Session Monitoring with Symmetric Receive-side Scaling</a><br />
<a href="https://www.kernel.org/doc/Documentation/networking/scaling.txt" rel="noopener" target="_blank">Scaling in the Linux Networking Stack</a><br />
<a href="https://github.com/Linaro/odp/blob/master/platform/linux-generic/odp_classification.c" rel="noopener" target="_blank">odp_classification.c</a></p>
<p>The post <a rel="nofollow" href="https://richliu.com/2018/06/11/2288/rss-hash-calculation-c-code/">RSS Toeplitz Hash Calculation C Code</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2018/06/11/2288/rss-hash-calculation-c-code/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Ubuntu 16.04 error: undefined reference to `create_module&#8217;</title>
		<link>https://richliu.com/2016/11/30/2044/ubuntu-16-04-error-undefined-reference-to-create_module/</link>
					<comments>https://richliu.com/2016/11/30/2044/ubuntu-16-04-error-undefined-reference-to-create_module/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Tue, 29 Nov 2016 16:31:56 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[16.04]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=2044</guid>

					<description><![CDATA[<p>Ubuntu 16.04 error: undefined reference to `create_modu [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2016/11/30/2044/ubuntu-16-04-error-undefined-reference-to-create_module/">Ubuntu 16.04 error: undefined reference to `create_module&#8217;</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Ubuntu 16.04 error: undefined reference to `create_module&#8217;</p>
<pre lang="text">Building module-init-tools-3.2 in Ubuntu16.04 failed:
lsmod.o: In function `try_old_version':
./module-init-tools-3.2/backwards_compat.c:56: undefined reference to `create_module'
</pre>
<p>這一篇<a href="http://mkl-note.blogspot.tw/2016/04/ubuntu-1604-error-undefined-reference.html" target="_blank" rel="noopener">Ubuntu 16.04 error: undefined reference to `create_module&#8217;</a>對我沒有用, 但是解法是對的, 這時就要用粗暴的方式, 直接改 backwards_compat.c<br />
加上 </p>
<pre lang="C">
#define CONFIG_NO_BACKWARDS_COMPAT 
</pre>
<p>暫時解決問題</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2016/11/30/2044/ubuntu-16-04-error-undefined-reference-to-create_module/">Ubuntu 16.04 error: undefined reference to `create_module&#8217;</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2016/11/30/2044/ubuntu-16-04-error-undefined-reference-to-create_module/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>SIGALARM / timer_create 造成 CPU sys 100% 的問題</title>
		<link>https://richliu.com/2016/09/01/2002/sigalarm-timer_create-%e9%80%a0%e6%88%90-cpu-sys-100-%e7%9a%84%e5%95%8f%e9%a1%8c/</link>
					<comments>https://richliu.com/2016/09/01/2002/sigalarm-timer_create-%e9%80%a0%e6%88%90-cpu-sys-100-%e7%9a%84%e5%95%8f%e9%a1%8c/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Thu, 01 Sep 2016 10:19:27 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[epoll]]></category>
		<category><![CDATA[pthread]]></category>
		<category><![CDATA[sigalrm]]></category>
		<category><![CDATA[timer_create]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=2002</guid>

					<description><![CDATA[<p>最近遇到一個怪問題, 某一隻程式跑起來的時候, 有一定的機率 sys 佔有率是 100% Cpu0  :  0 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2016/09/01/2002/sigalarm-timer_create-%e9%80%a0%e6%88%90-cpu-sys-100-%e7%9a%84%e5%95%8f%e9%a1%8c/">SIGALARM / timer_create 造成 CPU sys 100% 的問題</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>最近遇到一個怪問題, 某一隻程式跑起來的時候, 有一定的機率 sys 佔有率是 100%</p>
<blockquote><p>Cpu0  :  0.0%us,<span style="color: #ff0000;">100.0%sy</span>,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st</p></blockquote>
<p><span id="more-2002"></span></p>
<p>原來的 code 長的像是這樣</p>
<pre lang="c">#include <time .h>
#include <stdio .h>
#include <errno .h>
#include <stdlib .h>
#include <string .h>
#include <signal .h>
#include <unistd .h>
#include <pthread .h>


#ifdef USE_SEM
sem_t g_timer_sem_hdlr;
#endif


void  sig_timer_hanler(void)
{
#ifdef USE_SEM
	sem_post(&amp;g_timer_sem_hdlr);
#endif
	return ;
}

void main(){

unsigned int period=1000;
	struct itimerval it_val;	/* for setting itimer */
	int i=0;
#ifdef USE_SEM
	sem_init(&amp;g_timer_sem_hdlr,1,0);
#endif

	if (signal(SIGALRM, (void (*)(int)) sig_timer_hanler) == SIG_ERR)
	{
		perror("Unable to catch SIGALRM");
		return ;
	}
	it_val.it_value.tv_sec =  0;
	it_val.it_value.tv_usec = period;
	it_val.it_interval = it_val.it_value;
	if (setitimer(ITIMER_REAL, &amp;it_val, NULL) == -1)
	{
		perror("error calling setitimer()");
		return ;
	}
	printf("test started.\n");
	while(1){
#ifdef USE_SEM
		sem_wait(&amp;g_timer_sem_hdlr);
#else
		usleep(1000);
#endif
		if((i%1000)==0) printf("%s: hello, i=%d\n",__func__,i);
		i++;
	}
	printf("exited.\n");
	return ;
}
</pthread></unistd></signal></string></stdlib></errno></stdio></time></pre>
<p>如果用 perf 下去看, 大概長得像這樣,  kernel space 的 wait 不是真正的 wait</p>
<pre lang="text">   
66.86%  swapper  [kernel.kallsyms]  [k] r4k_wait
        |
        --- r4k_wait
        cpu_idle

32.21%    test  test               [.] main
0.12%     test  [kernel.kallsyms]  [k] finish_task_switch
        |
        --- finish_task_switch
        |
        |--54.54%-- __schedule
        |          schedule
        |          |
        |          |--83.34%-- work_resched
        |          |
        |           [--16.66%-- schedule_timeout
        |                     do_sigtimedwait
        |                     SyS_rt_sigtimedwait
        |                     handle_sys64
        |
        --45.46%-- schedule_tail
</pre>
<p>打開 kernel spin lock stat 也看不出所以然來(註: 上面是 100% sys cpu 的, 下面是正常的</p>
<p><div id="attachment_2003" style="width: 310px" class="wp-caption aligncenter"><a href="https://richliu.com/wp-content/uploads/2016/08/spinlock.png"><img loading="lazy" decoding="async" aria-describedby="caption-attachment-2003" class="size-medium wp-image-2003" src="https://richliu.com/wp-content/uploads/2016/08/spinlock-300x145.png" alt="spinlock" width="300" height="145" srcset="https://richliu.com/wp-content/uploads/2016/08/spinlock-300x145.png 300w, https://richliu.com/wp-content/uploads/2016/08/spinlock-768x371.png 768w, https://richliu.com/wp-content/uploads/2016/08/spinlock-1024x495.png 1024w" sizes="auto, (max-width: 300px) 100vw, 300px" /></a><p id="caption-attachment-2003" class="wp-caption-text">spinlock</p></div></p>
<p>所以這就讓人很困擾, 到底出了什麼問題<br />
做過一些測試, 例如:<br />
Enable Realtime option , 改用 tickless or 1000HZ tick , 檢查 spin lock deadlock ,<br />
叫出 Sysrq 出來看(看不出來有什麼特別的)<br />
不過仍然會發生, 百思不得其解.</p>
<p>除了自己的 Embedded System , 連 Ubuntu PC 也可以複製的出來,<br />
所以這就排除了 SoC vendor 的問題, 理論上我們的應用不是特別奇怪.<br />
所以心中訥悶, 這世界上這麼多人只有我們有問題嗎?</p>
<p>關於這個問題的人討論的很少, 所以可能要多翻一下 Google , 多濾一些關鍵字.</p>
<p>直到翻到這個網站, <a href="https://nativeguru.wordpress.com/2015/02/19/why-you-should-avoid-using-sigalrm-for-timer/" target="_blank" rel="noopener">WHY YOU SHOULD AVOID USING SIGALRM FOR TIMER</a><br />
他的說法是</p>
<blockquote><p>The problem occurs when the signal function is triggered just before we call setitimer().<br />
The signal handler blocks, as the mutex is currently being held by do_timer_bookkeeping() and this is the deadlock.</p></blockquote>
<p>不過我們沒有 deadlock , 但是他的發想很好, 仍然可以參考他講的去做</p>
<blockquote><p>To fix it, I removed all the SIGALRM code and replaced it with setitimer.<br />
I set the previous SIGALRM handler as the thread that will be spawned whenever the timer expired.</p></blockquote>
<p>看起來是好主義</p>
<p>所以我就用 timer_create 改寫了一下這隻程式,<br />
好的事情是, 情況有改善, 不會在 10 分鐘就發生,<br />
壞的事情是, 仍然會發生. 雖然極難複製這個問題, 但是會發生就是很討厭, 會留一個尾巴沒有辦法收尾.</p>
<p>所以持續在看有沒有其他的解決方案.<br />
(timer_create 的寫法可以參考<a href="https://wirelessr.gitbooks.io/working-life/content/linux_timer.html" target="_blank" rel="noopener"> Linux timer</a>)</p>
<p>中間有翻到 pthread 的 sigmask 用 thread 處理 SIGALRM 訊號,<br />
不過多想一下, 個人認為應該也會踏到同樣的問題, 所以做完功課之後, 這個方式晚一點再說.</p>
<p>又翻到這一篇<a href="http://stackoverflow.com/questions/2586926/setitimer-sigalrm-multithread-process-linux-c" target="_blank" rel="noopener">setitimer, SIGALRM &amp; multithread process (linux, c) </a>其中有說到,</p>
<blockquote><p>In the topic, Andi Kleen (Intel) <a href="https://lkml.org/lkml/2010/4/11/81" rel="nofollow noopener" target="_blank">recommends to switch to</a> &#8220;<em>POSIX timers (<a href="http://pubs.opengroup.org/onlinepubs/7908799/xsh/timer_create.html" rel="nofollow noopener" target="_blank"><code>timer_create</code></a>)</em>&#8220;; and in <a href="https://lkml.org/lkml/2010/4/11/92" rel="nofollow noopener" target="_blank">ML thread</a> Davide Libenzi suggests use of <code>timerfd</code> (timerfd_create, timerfd_settime) on non-ancient Linuxes.</p></blockquote>
<p>答案就呼之欲出了, 要改用 timerfd 改寫我目前的 timer_create.<br />
不過 timerfd 是 trigger fd 用的, 不會呼叫 call back function, 所以要配合 epoll 用, 而且 epoll 是 IO event trigger , 所以要配合 pthread 去處理 epoll .</p>
<p>程式改寫完的結果, 看起來效能比 SIGALRM / timer_create 好. 但是複雜許多, 有<del>抄</del>參考別人的 sample code ,<br />
不過考量這些 code 要處理 multiple fd, 而我目地只是取代原來的 SIGALRM, 所以又再更精簡化, 一般會更複雜的.</p>
<p>程式碼</p>
<pre lang="C">#include <stdio .h>
#include <stdlib .h>
#include <sys /time.h>
#include <pthread .h>
#include <semaphore .h>
#include <signal .h>
#include <unistd .h>
#include <time .h>
#include <sys /epoll.h>
#include </sys><sys /timerfd.h>


sem_t g_timer_sem_hdlr;
int timerfd;
pthread_t sig_thread;

#define MAX_EVENT 4

static int      epfd = -1;
static struct   epoll_event events ;
static int      sig_timer;
static struct itimerspec        its;
static struct epoll_event      ev;


void *sig_epoll_wait( void *ptr){
    int numEvent=0;
    unsigned long value;
    struct event_record *pevent = NULL;
    int i;

    while(1){
        numEvent = epoll_wait( epfd, &amp;events,1 , -1 );

        for( i=0; i &lt; numEvent ; i++){

            if( epoll_ctl( epfd, EPOLL_CTL_DEL, timerfd, &amp;ev) == -1)
                perror("[1] epoll_ctl del");

            if(timerfd_settime( timerfd, 0, &amp;its, NULL ) == -1 )
                perror("[1] timerfd_settime");

            if( epoll_ctl( epfd, EPOLL_CTL_ADD, timerfd, &amp;ev) == -1)
                perror("[1] epoll_ctl add");
            sem_post(&amp;g_timer_sem_hdlr);
        }
    }

    return NULL;
}

void create_timer(int sig, int msec)
{

    timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
    if( timerfd == -1)
        perror("timerfd_create");

    its.it_value.tv_sec = 0;
    its.it_value.tv_nsec = msec * 1000000;
    its.it_interval.tv_sec = its.it_value.tv_sec;
    its.it_interval.tv_nsec = its.it_value.tv_nsec;

    if ( timerfd_settime( timerfd, 0, &amp;its, NULL ) == -1 )
        perror( "timerfd_settime" );

    // Create epoll
    epfd = epoll_create( 1 );
    if ( epfd == -1 )
        perror(" epoll_create ");

    ev.data.ptr = &amp;sig_timer;
    ev.events   = EPOLLIN | EPOLLET;

    // enable epoll

    if( epoll_ctl( epfd, EPOLL_CTL_ADD, timerfd, &amp;ev) == -1)
        perror("[0] epoll_ctl");

    // Create Thread
    pthread_create(&amp;sig_thread, NULL , sig_epoll_wait , NULL);

}

void main(){
    int i=0;
    sem_init(&amp;g_timer_sem_hdlr,1,0);

    printf("Create Timer \n");
    create_timer(5566, 5);  // ms
    while(1){
        sem_wait(&amp;g_timer_sem_hdlr);
        if((i%10000)==0) printf("%s: hello, i=%d\n",__func__,i);
        i++;
    }
    printf("exited.\n");
    return ;
}


</sys></time></unistd></signal></semaphore></pthread></sys></stdlib></stdio></pre>
<p>其他有些資訊是提到 top 計算不準的問題</p>
<p>https://www.kernel.org/doc/Documentation/cpu-load.txt<br />
https://lkml.org/lkml/2007/2/12/6</p>
<p>ref.</p>
<ul>
<li><a href="https://github.com/seiyak/ssebot-samples/blob/master/sample-timerfd-epoll.c" target="_blank" rel="noopener">Linux FD Handler 以及 Timer 機制</a></li>
<li><a href="https://github.com/seiyak/ssebot-samples/blob/master/sample-timerfd-epoll.c" target="_blank" rel="noopener">ssebot-samples/sample-timerfd-epoll.c : </a>這 code 寫的不錯, 主要是學習這個的.</li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2016/09/01/2002/sigalarm-timer_create-%e9%80%a0%e6%88%90-cpu-sys-100-%e7%9a%84%e5%95%8f%e9%a1%8c/">SIGALARM / timer_create 造成 CPU sys 100% 的問題</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2016/09/01/2002/sigalarm-timer_create-%e9%80%a0%e6%88%90-cpu-sys-100-%e7%9a%84%e5%95%8f%e9%a1%8c/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>git subversion</title>
		<link>https://richliu.com/2013/12/30/1593/git-subversion/</link>
					<comments>https://richliu.com/2013/12/30/1593/git-subversion/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Mon, 30 Dec 2013 14:16:44 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1593</guid>

					<description><![CDATA[<p>git 真是很難操控的東西. 好像寫了很多次, 但是都忘記怎麼用.. # git svn clone svn: [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2013/12/30/1593/git-subversion/">git subversion</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>git 真是很難操控的東西. 好像寫了很多次, 但是都忘記怎麼用..<br />
<span id="more-1593"></span><br />
# git svn clone svn://blah blah </p>
<p>Update source code.<br />
# git svn fetch<br />
# git svn rebase </p>
<p>git 不能用 bare 當作 svn 的 repository. 只能用 work repository<br />
所以如果有其他目錄 clone 出去要 commit 進來時, 可以用這個指令</p>
<p># git push origin master:origin<br />
將自己的 master 推到 remote 的 origin 去, 有時候 origin 存在時無法 push, 就換另一個名字再 push. </p>
<p># git push origin master:origin3</p>
<p>然後在原來的 repository 應該就可以 commit 了<br />
# git svn dcommit</p>
<p>如果沒有辦法, 可以切到 master<br />
# git checkout master<br />
再下 cherry-pick (只上 patch), 如果什麼都不下, 就是只上一個 patch<br />
# git cherry-pick origin<br />
如果要上很多 patch<br />
# git cherry-pick start_patch^..end_patch<br />
這邊要用 start_patch 的前一版, 我也不知道為什麼啦. </p>
<p>如果一次改了很多 bug 要分別 patch<br />
可以用<br />
# git add -p<br />
這時候就會一個 diff 一個 diff 列, 命令列還有 s (split), e(edit) 可以將 diff 分成兩個和修改. </p>
<p>做完之後<br />
# git diff &#8211;cached<br />
看己經儲存的 patch<br />
# git commit<br />
不能用 -a , 這樣會連其他的一起 commit </p>
<p>commit 錯了<br />
# git reset HEAD^<br />
可以重新 commit 一次<br />
清除 code.<br />
# git reset &#8211;hard<br />
如果只是打錯 commit 的說明<br />
# git commit &#8211;amend</p>
<p>其他太複雜的就暫時不研究了. </p>
<p>The post <a rel="nofollow" href="https://richliu.com/2013/12/30/1593/git-subversion/">git subversion</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2013/12/30/1593/git-subversion/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>HTC One XL Jelly Bean ROM</title>
		<link>https://richliu.com/2013/04/29/1465/htc-one-xl-jelly-bean-rom/</link>
					<comments>https://richliu.com/2013/04/29/1465/htc-one-xl-jelly-bean-rom/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Mon, 29 Apr 2013 12:41:16 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[CleanROM]]></category>
		<category><![CDATA[HTC One XL]]></category>
		<category><![CDATA[Jelly Bean]]></category>
		<category><![CDATA[升級]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1465</guid>

					<description><![CDATA[<p>今天將 HTC One XL AT&#38;T 版升 Jelly Bean 了. 感覺比 CleanROM 5 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2013/04/29/1465/htc-one-xl-jelly-bean-rom/">HTC One XL Jelly Bean ROM</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>今天將 HTC One XL AT&amp;T 版升 Jelly Bean 了.<br />
感覺比 CleanROM 5 (Ice cream) 有著長足的進步.<br />
之前的頓挫感不見了, 感覺手機升級了.<br />
<span id="more-1465"></span><br />
我總共測過二版 ROM</p>
<p>(1) <a href="http://forum.xda-developers.com/showthread.php?t=1655011" target="_blank" rel="noopener">CleanROM 6 R2 </a></p>
<p style="padding-left: 30px;">這版是從 AT&amp;T Stock ROM 改的, AT&amp;T 版該有的缺點都有, 沒有 Wifi/USB Tether. 3G 的圖案是 4G 等等.<br />
不過這版靠杯快的, 超順, 大概和 HTC Butterfly 一樣快.<br />
聽說換 <a href="http://forum.xda-developers.com/showthread.php?t=2136403" target="_blank" rel="noopener">CleanRom JL Beta1 </a>這一版就可以 Tether, 不過我沒有試</p>
<p>(2) <a href="http://forum.xda-developers.com/showthread.php?t=2055490" target="_blank" rel="noopener">Stock Asia Rom</a></p>
<p style="padding-left: 30px;">這版應該是從 ASIA 國際版 dump 出來的, 速度比 CleanROM R6 稍慢, 但是整體來說順暢很多(到底是不是我的 ICS CleanROM 5 太慢呀).<br />
Wifi/USB Tether 皆可使用,</p>
<p style="padding-left: 30px;">我本來有裝<a href="https://play.google.com/store/apps/details?id=com.googlecode.android.wifi.tether" target="_blank" rel="noopener">WiFi Tether for Root Users</a>,先執行似乎會和原生的 Wifi/USB Tethering 相衝, 我重開機不執行它, 執行內建的 Wifi/USB tethering 就 OK 了.</p>
<p style="padding-left: 30px;">HTC Input 只有英文語系, 其他語系要下載, 有朋友回報手寫下載有問題(我沒有試, 幾乎用不到), 不過注音沒有問題.<br />
第一次使用 HTC Input 的中文有當掉的情況, 重開機就解決了.</p>
<p style="padding-left: 30px;">升上去 Jelly Bean 之後, Mount Disk 變 MTP protocol, 要注意一下.</p>
<p>ICS 升 Jelly Bean 要 Wipe Data 才可以升級, 所以記得先備份.<br />
備份回復系統的時候, 如果是用 ASIA Stock ROM, 記得要先升級完連絡人和相機之後再執行回復. 要不然會有奇怪的狀況.</p>
<p>目前用到現在似乎 OK.<br />
觀察中. 做個記錄, 給其他想踩地雷的人參考(應該沒有多少人有吧 XDD)</p>
<p>用了二天的感想就是待機時間更省電了, 約為 CleanROM 5 的 40% 左右, 平常瀏覽網頁(Firefox)速度也快很多, 至於一般使用感覺還是一樣耗電, 這就沒有辦法了&#8230;<br />
這一版調教的還不錯.</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2013/04/29/1465/htc-one-xl-jelly-bean-rom/">HTC One XL Jelly Bean ROM</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2013/04/29/1465/htc-one-xl-jelly-bean-rom/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[GIT] 將現有的目錄改成 bare 並且修改 remote server</title>
		<link>https://richliu.com/2012/11/15/1351/git-%e5%b0%87%e7%8f%be%e6%9c%89%e7%9a%84%e7%9b%ae%e9%8c%84%e6%94%b9%e6%88%90-bare-%e4%b8%a6%e4%b8%94%e4%bf%ae%e6%94%b9-remote-server/</link>
					<comments>https://richliu.com/2012/11/15/1351/git-%e5%b0%87%e7%8f%be%e6%9c%89%e7%9a%84%e7%9b%ae%e9%8c%84%e6%94%b9%e6%88%90-bare-%e4%b8%a6%e4%b8%94%e4%bf%ae%e6%94%b9-remote-server/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Wed, 14 Nov 2012 17:56:08 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[bare]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[remote]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1351</guid>

					<description><![CDATA[<p>git 如果從另一個目錄 clone 出來, 兩邊都有 source code, 是不能直接 master p [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2012/11/15/1351/git-%e5%b0%87%e7%8f%be%e6%9c%89%e7%9a%84%e7%9b%ae%e9%8c%84%e6%94%b9%e6%88%90-bare-%e4%b8%a6%e4%b8%94%e4%bf%ae%e6%94%b9-remote-server/">[GIT] 將現有的目錄改成 bare 並且修改 remote server</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>git 如果從另一個目錄 clone 出來, 兩邊都有 source code, 是不能直接 master push 到 master 的.<br />
會出現錯誤訊息<br />
[TEXT]<br />
git push error &#8216;[remote rejected] master -> master (branch is currently checked out)&#8217;<br />
[/TEXT]</p>
<p>這時可以產生另一個 bare 目錄, 然後到 git 目錄內下指令, 將該目錄變成 bare<br />
[BASH]<br />
# cp -a (path_to_source_dir) (path_to_bare_dir)<br />
# cd (path_to_bare_dir)<br />
# git config &#8211;bool core.bare true<br />
# rm (all source code)<br />
# mv .git/* .<br />
# rmdir .git<br />
[/BASH]</p>
<p>這樣就可以了. </p>
<p>原來的目錄可以修改 remote url 的方式指到新的目錄<br />
[BASH]<br />
# cd (path_to_source_dir)<br />
# git remote set-url origin //(path_to_bare_dir)<br />
[/BASH]</p>
<p>這時有 source code 的目錄還是用 git push/pull 更新 source code.<br />
如果是 bare 的話就是 git push, git fetch/merge 更新 source code. </p>
<p>Ref web.<br />
<a href="http://stackoverflow.com/questions/2816369/git-push-error-remote-rejected-master-master-branch-is-currently-checked" target="_blank" rel="noopener">http://stackoverflow.com/questions/2816369/git-push-error-remote-rejected-master-master-branch-is-currently-checked</a><br />
<a href="http://stackoverflow.com/questions/2432764/how-to-change-a-remote-repository-uri-using-git" target="_blank" rel="noopener">http://stackoverflow.com/questions/2432764/how-to-change-a-remote-repository-uri-using-git</a></p>
<p>The post <a rel="nofollow" href="https://richliu.com/2012/11/15/1351/git-%e5%b0%87%e7%8f%be%e6%9c%89%e7%9a%84%e7%9b%ae%e9%8c%84%e6%94%b9%e6%88%90-bare-%e4%b8%a6%e4%b8%94%e4%bf%ae%e6%94%b9-remote-server/">[GIT] 將現有的目錄改成 bare 並且修改 remote server</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2012/11/15/1351/git-%e5%b0%87%e7%8f%be%e6%9c%89%e7%9a%84%e7%9b%ae%e9%8c%84%e6%94%b9%e6%88%90-bare-%e4%b8%a6%e4%b8%94%e4%bf%ae%e6%94%b9-remote-server/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>[敗家] HTC One XL AT&#038;T 版.</title>
		<link>https://richliu.com/2012/06/06/1230/%e6%95%97%e5%ae%b6-htc-one-xl-att-%e7%89%88/</link>
					<comments>https://richliu.com/2012/06/06/1230/%e6%95%97%e5%ae%b6-htc-one-xl-att-%e7%89%88/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Wed, 06 Jun 2012 15:16:10 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[敗家誌]]></category>
		<category><![CDATA[AT&T]]></category>
		<category><![CDATA[HTC One X]]></category>
		<category><![CDATA[HTC One XL]]></category>
		<category><![CDATA[unlock]]></category>
		<category><![CDATA[Unlock Sim]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1230</guid>

					<description><![CDATA[<p>我沒事找自己麻煩做什麼 -___- 剛剛入手一隻 HTC One X AT&#38;T 版, 一般稱這個版本為 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2012/06/06/1230/%e6%95%97%e5%ae%b6-htc-one-xl-att-%e7%89%88/">[敗家] HTC One XL AT&#038;T 版.</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>我沒事找自己麻煩做什麼 -___-</p>
<p>剛剛入手一隻 HTC One X AT&amp;T 版, 一般稱這個版本為 HTC One XL.</p>
<p>不過因為有鎖 AT&amp;T 的 sim 卡才能使用, 所以國外使用比較不便.</p>
<p>P.S 這隻手機也有人叫, HTC ONE X ATT Version .<br />
&#8212;<br />
<a href="https://richliu.com/wp-content/uploads/2012/06/chunghwa-htc-one-xl-unlock_7345211872_o.png"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-3272" src="https://richliu.com/wp-content/uploads/2012/06/chunghwa-htc-one-xl-unlock_7345211872_o-576x1024.png" alt="" width="576" height="1024" srcset="https://richliu.com/wp-content/uploads/2012/06/chunghwa-htc-one-xl-unlock_7345211872_o-576x1024.png 576w, https://richliu.com/wp-content/uploads/2012/06/chunghwa-htc-one-xl-unlock_7345211872_o-169x300.png 169w, https://richliu.com/wp-content/uploads/2012/06/chunghwa-htc-one-xl-unlock_7345211872_o.png 720w" sizes="auto, (max-width: 576px) 100vw, 576px" /></a></p>
<p><strong><span style="color: #ff0000;">以下的動作都有風險讓你的 HTC One XL 變磚, 本人不負任何責任</span></strong><br />
先不要升級, 預設出廠的 Firmware 版本是比較容易升級的.</p>
<p>如果要買回台灣用, 至少要做 Sim Unlock , 要花點錢去買 Unlock code.<br />
我是在<a href="http://www.htcsimunlock.com/" target="_blank" rel="noopener">http://www.htcsimunlock.com/</a>買的, US$12.95.-<br />
Unlock Code 是可以用的.</p>
<p>內建的輸入法就有中文, 顯示中文也沒有問題</p>
<p>接下來可以 root, 請參考這一篇.<br />
<a href="http://forum.xda-developers.com/showthread.php?t=1644167" target="_blank" rel="noopener"> [ROOT] One Click HTC One X (AT&amp;T/Rogers/Others) (Win/Mac/Linux)</a></p>
<p>root 完要 unlock bootloader<br />
<a href="http://briefmobile.com/how-to-unlock-att-one-x-bootloader" target="_blank" rel="noopener">How To: Unlock AT&amp;T One X Bootloader</a></p>
<p>然後就可以升級 RUU v1.85.502 . 感覺升完最新的 RUU 之後, 3G Data 網路比較正常.<br />
這部的的文章可以參考這一篇.<br />
<a href="http://forum.xda-developers.com/showthread.php?t=1678138" target="_blank" rel="noopener">[TUTORIAL] Prepare Your AT&amp;T HTC One X for Custom ROMs</a></p>
<p>簡單的說明步驟<br />
1) Relock (重新 lock) 之後才能進行 RUU 升級<br />
2) 執行 RUU 進行系統升級<br />
3) 用之前的 unlock token file 再 unlock , 在 bootloader 會看到 UNLOCKER 字樣, 這個步驟有可能要跑非常非常多次, 有人一次就成功, 有人跑了二小時, 我大概 flash 了有 20 次吧.<br />
4) 燒新的 Recovery , 有二個, CWM , ClockWorkMod Touch 及 TWRP (TeamWinRecoveryProject). 我 TWRP 開不起來, 最後是用 CWM 才成功.<br />
5) 用 Recovery 燒之前 SuperRoot 的 root.zip, 可以躲過其他權限讓 su 取得 superuser 的 right. 這樣就 OK 了.</p>
<p>這樣就有了一個最新版 Firmware 的 AT&amp;T HTC One XL 手機.</p>
<p>最後就是移除討人厭的 Bloatware 了<br />
<a href="http://forum.xda-developers.com/showthread.php?t=1678308" target="_blank" rel="noopener">[HOW TO] How to do virtually everything to your ONE X &#8230;</a><br />
這篇文章的內有一個 Link, 點下去之後會下載一個 PDF File, 依照第八章的方式移除 Apk 和 resource file<br />
這樣就不會有討人厭的 AT&amp;T 相關 resource 了</p>
<p>Tethering 也己得要開, AT&amp;T 這個功能要收錢的<br />
<a href="http://forum.xda-developers.com/showthread.php?t=1677261" target="_blank" rel="noopener">http://forum.xda-developers.com/showthread.php?t=1677261</a></p>
<p>Wifi Tether<br />
<a href="http://forum.xda-developers.com/showthread.php?t=1646795&amp;page=2" target="_blank" rel="noopener">http://forum.xda-developers.com/showthread.php?t=1646795&amp;page=2</a></p>
<p>最後一步, 要刷 ASIA 版的 Radio 看起來 3G 才會比較正常一點, 如果有人還沒有刷的可以先測試一下自己的 3G 是不是正常<br />
我刷之前 3G DATA 都無法順利使用<br />
<a href="http://forum.xda-developers.com/showthread.php?t=1694012" target="_blank" rel="noopener">http://forum.xda-developers.com/showthread.php?t=1694012</a></p>
<p>這是 SpeedTest 的結果, 上傳慢很多, 不過可以接受了, 而且 Server 是放在遠傳電信, 可能會有誤差<br />
<a href="https://richliu.com/wp-content/uploads/2012/06/2012-06-08-025228_7163887821_o.png"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-3273" src="https://richliu.com/wp-content/uploads/2012/06/2012-06-08-025228_7163887821_o-576x1024.png" alt="" width="576" height="1024" srcset="https://richliu.com/wp-content/uploads/2012/06/2012-06-08-025228_7163887821_o-576x1024.png 576w, https://richliu.com/wp-content/uploads/2012/06/2012-06-08-025228_7163887821_o-169x300.png 169w, https://richliu.com/wp-content/uploads/2012/06/2012-06-08-025228_7163887821_o.png 720w" sizes="auto, (max-width: 576px) 100vw, 576px" /></a></p>
<p>至少 Google Play 可以下載了.</p>
<p>希望這篇有幫到有想要買 HTC One X AT&amp;T 版人的忙.. :p</p>
<p>&#8212; 20120626 Update &#8212;<br />
如果系統整個爛了, 開不了機, 那就要 relock 之後抓 <a href="http://forum.xda-developers.com/showthread.php?t=1670238" target="_blank" rel="noopener">RUU</a> 下來 Update Firmware.<br />
RUU 內有原來的 Radio, kernel 和 system file.<br />
像是 &#8220;Can&#8217;t Find SDCard&#8221; 這樣的怪問題也可以用這個方法解決掉.</p>
<p>只要 fastboot 進得去, 就可以用這一招恢復變磚的系統.<br />
然後我現在沒有用 Stock ROM, 改用 <a href="http://forum.xda-developers.com/showthread.php?t=1655011" target="_blank" rel="noopener">Clean Rom SE</a>, 試試看會不會比較好.</p>
<p>&#8212; 20140120 Update &#8212;<br />
升級到 3.18 RUU, 升完之後才可以刷 TWRP 2.6.3.0-SELinux 版.<br />
才可以刷 4.2.2<br />
升 RUU 之前要先 S-OFF<br />
http://forum.xda-developers.com/showthread.php?t=2155071<br />
RUU 升級方法<br />
http://forum.xda-developers.com/showthread.php?t=2593037<br />
TWRP 2.6.3.9-SELinux 版<br />
http://forum.xda-developers.com/showthread.php?t=2558503<br />
CM 11.0<br />
http://forum.xda-developers.com/showthread.php?p=44053927</p>
<p>ref.<br />
<a href="http://forum.xda-developers.com/showthread.php?t=1671237" target="_blank" rel="noopener">[INDEX] AT&amp;T/ROGERS One X Resources Compilation Roll-Up (6/5/12)</a></p>
<p>The post <a rel="nofollow" href="https://richliu.com/2012/06/06/1230/%e6%95%97%e5%ae%b6-htc-one-xl-att-%e7%89%88/">[敗家] HTC One XL AT&#038;T 版.</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2012/06/06/1230/%e6%95%97%e5%ae%b6-htc-one-xl-att-%e7%89%88/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>KEIL uVersion Link Error</title>
		<link>https://richliu.com/2012/02/15/1197/keil-uversion-link-error/</link>
					<comments>https://richliu.com/2012/02/15/1197/keil-uversion-link-error/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Tue, 14 Feb 2012 16:56:00 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[keil]]></category>
		<category><![CDATA[link error]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1197</guid>

					<description><![CDATA[<p>Compile 時最後碰到這個問題. 這是在 C 中去 Link C++ 的 Code 產生的. [TEXT] [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2012/02/15/1197/keil-uversion-link-error/">KEIL uVersion Link Error</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Compile 時最後碰到這個問題. </p>
<p>這是在 C 中去 Link C++ 的 Code 產生的. </p>
<p>[TEXT]<br />
linking&#8230;<br />
.\Obj\Memory.axf: Error: L6218E: Undefined symbol __aeabi_unwind_cpp_pr0 (referred from array_new.o).<br />
.\Obj\Memory.axf: Error: L6218E: Undefined symbol __rt_new_handler_addr (referred from new.o).<br />
.\Obj\Memory.axf: Error: L6218E: Undefined symbol abort (referred from arm_exceptions_terminate.o).<br />
.\Obj\Memory.axf: Error: L6218E: Undefined symbol __rt_eh_globals_addr (referred from arm_exceptions_globs.o).<br />
Target not created<br />
[/TEXT]</p>
<p>解決方法就是 Option -> Target -> Use MicroLib 關掉. </p>
<p>如果要引入一些標準的 C Library, 也不能使用 MicroLib .<br />
像是要初始化 <a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0349bc/Cihfiabf.html" target="_blank" rel="noopener">Heap , _init_alloc</a> 也是要關掉 MicroLib 的支援. </p>
<p>註:<br />
當使用 malloc 時, 會去 heap 取得一塊 memory 給程式使用, 但是<br />
Keil 本身並沒有 heap 的管理機制, 要指定一塊 memory 給 heap 用.<br />
這時就要先 initial heap, 要使用 _init_alloc 這個 function 才可以 allocate . </p>
<p>Ref.<br />
<a href="http://www.keil.com/arm/microlib.asp" target="_blank" rel="noopener">MicroLib</a></p>
<p>The post <a rel="nofollow" href="https://richliu.com/2012/02/15/1197/keil-uversion-link-error/">KEIL uVersion Link Error</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2012/02/15/1197/keil-uversion-link-error/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Kindle Fire 開箱文 (加贈 Root 成功文, 6.2.1 root 文)</title>
		<link>https://richliu.com/2011/12/01/1144/kindle-fire-%e9%96%8b%e7%ae%b1%e6%96%87-%e5%8a%a0%e8%b4%88-root-%e6%88%90%e5%8a%9f%e6%96%87/</link>
					<comments>https://richliu.com/2011/12/01/1144/kindle-fire-%e9%96%8b%e7%ae%b1%e6%96%87-%e5%8a%a0%e8%b4%88-root-%e6%88%90%e5%8a%9f%e6%96%87/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Wed, 30 Nov 2011 18:13:35 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[敗家誌]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[kindle fire]]></category>
		<category><![CDATA[root]]></category>
		<category><![CDATA[中文輸入]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1144</guid>

					<description><![CDATA[<p>在 101 地下室餐廳吃飯, 從 101 樓上跑出來一個箱子. 這年頭什麼都可以撿, 小弟撿到這個不到 10K [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2011/12/01/1144/kindle-fire-%e9%96%8b%e7%ae%b1%e6%96%87-%e5%8a%a0%e8%b4%88-root-%e6%88%90%e5%8a%9f%e6%96%87/">Kindle Fire 開箱文 (加贈 Root 成功文, 6.2.1 root 文)</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>在 101 地下室餐廳吃飯, 從 101 樓上跑出來一個箱子.<br />
<a title="DSC00375 by richliu(有錢劉), on Flickr" href="http://www.flickr.com/photos/richliu_tw/6431643655/" target="_blank" rel="noopener"><img loading="lazy" decoding="async" src="http://farm8.staticflickr.com/7004/6431643655_73a5131377.jpg" alt="DSC00375" width="375" height="500" /></a><br />
這年頭什麼都可以撿, 小弟撿到這個不到 10K. 算便宜的.</p>
<p><span id="more-1144"></span></p>
<p>打開一看</p>
<p><a title="DSC00376 by richliu(有錢劉), on Flickr" href="http://www.flickr.com/photos/richliu_tw/6431645543/" target="_blank" rel="noopener"><img loading="lazy" decoding="async" src="http://farm8.staticflickr.com/7143/6431645543_8229cd6950.jpg" alt="DSC00376" width="375" height="500" /></a></p>
<p>原來是 Kindle Fire&#8230;.. (靠杯, 真無聊的開箱文)</p>
<p>感謝某位 Open Source 界知名的大大幫忙合購,<br />
費用加起來不到 6400 元.</p>
<p>不過現在入手 Kindle Fire 並不是一個好的時機, 甚至不是一個好的標地, 大家在購買之前要先想清楚<br />
你的目地是什麼.<br />
我只是想要一台入門平板, 偶爾可以拿來看個書, 這個價位是非常漂亮的.</p>
<p>Kindle Fire 海外大概只有書可以下載, 其他 Streaming, MP3 需要美國的 IP 才能下載(購買?)<br />
Apps 必須要是美國的地址和美國的信用卡才可以使用.<br />
Streaming 可能在 root 之後就沒有辦法使用, 目前這是 root 過的機器大家都有回報過的問題.<br />
我的 Amazon 帳戶是海外的, 所以這一部份我就不想了, 直接想 root 吧.<br />
還好 Kindle Fire root 還算簡單, 大家怕的只是沒有人做過而己.<br />
以下就是我收集到的資訊 (其實也不簡單啦)<br />
分享給大家一下.</p>
<p><span style="color: #ff0000;">* 以下過程有風險, 請自行考量風險, 本人不負任何責任 *</span></p>
<h2>安裝 Dropbox</h2>
<p>Kindle Fire 是可以安裝 Application 進去的, 要去 System Setting -&gt; Devices -&gt; Allow Installation of Applications.<br />
選 Enable,<br />
然後用 Web 到 https://www.dropbox.com/android/ 下載 Dropbox 的應用程式,<br />
如果沒有 Dropbox 的帳號, 可以從 <a href="http://db.tt/MMoOFTn" target="_blank" rel="noopener">http://db.tt/MMoOFTn</a> 這邊點進去申請, 這樣也可以幫我增加 Dropbox 的空間<br />
下載以後, 可以看這篇文章<br />
<a href="http://www.pcmag.com/article2/0,2817,2396276,00.asp" target="_blank" rel="noopener">How To Run Almost Any Android App On the Kindle Fire</a><br />
將 Android 手機中的 Astro File Manager 備份出來丟到 kindle Fire 內<br />
當然也可以直接接 MicroUSB 接到電腦, 在這之前請先準備 MicroUSB 的接頭.<br />
我是都用, 有時候懶得切來切去就用 Dropbox 丟檔案.</p>
<h2>升級 Kindle Fire Firmware 到 6.2</h2>
<p><del>先升級一下比較好, 免得 root 完了想升還要 unroot 很麻煩,</del><br />
<del> 從以下這個網址下載 Firmware 並且升級</del><br />
<del> <a href="http://www.amazon.com/gp/help/customer/display.html?nodeId=200790620" target="_blank" rel="noopener">http://www.amazon.com/gp/help/customer/display.html?nodeId=200790620</a></del><br />
<del> * 如果有想要用 CM7, 就先不要升級了.</del><br />
20111222: 不建議升級, 最近 Amazon 升級到 6.2.1, 就不能 root 了.</p>
<h2>root</h2>
<p>目前查到 Root 的方法有二種, 一種是照 kindlefireroot.com 的文章走, 另一種是用 SuperOneClick 的方式 root,<br />
我自己是用 kindlefireroot.com 的方式, 不過我想二種都 OK.<br />
* <a href="http://rootkindlefire.com/kindle-fire-root/how-to-root-kindle-fire/" target="_blank" rel="noopener">kindlefireroot.com root</a></p>
<p><a href="http://forum.xda-developers.com/showthread.php?t=803682" target="_blank" rel="noopener">SuperOneClick Download</a><br />
<a href="http://forum.xda-developers.com/showthread.php?t=1348830" target="_blank" rel="noopener">SuperOneClick for Kindle Fire How to</a></p>
<h2>安裝 Google Market</h2>
<p><a href="http://forum.xda-developers.com/showthread.php?t=1351283" target="_blank" rel="noopener">[GUIDE] Install Full Android Market on Kindle Fire (Compilation Master Thread)</a><br />
照以上這一篇文章做, 會缺少 Vending.apk, 以下是 Download Link<br />
<a href="http://forum.xda-developers.com/showthread.php?t=1364447" target="_blank" rel="noopener">Vending.apk download</a><br />
當然強者如我們就不需要什麼 root explorer 了, 直接用 adb.exe shell 進去, 下指令就可以了<br />
[BASH]<br />
# su<br />
# busybox mount -o remount,rw /system<br />
# cp /sdcard/dropbox/Vending.apk /system/app<br />
# chmod 644 /system/app/Vending.apk<br />
[/BASH]<br />
接下來要將 Amazon Market 關掉, 這樣就會使用系統預設的 Google Market<br />
[BASH]<br />
# cd /system/app<br />
# mv MarketIntentProxy.apk MarketIntentProxy.apk.bak<br />
[/BASH]</p>
<p>如果要看到 Google Market, 那要改用其他的桌面軟體, 上面那個 Link 有提到 Go Launcher Ex<br />
這個可以用, 補上 Screen Shot<br />
<a title="DSC00377 by richliu(有錢劉), on Flickr" href="http://www.flickr.com/photos/richliu_tw/6431647371/" target="_blank" rel="noopener"><img loading="lazy" decoding="async" src="http://farm8.staticflickr.com/7167/6431647371_70646e8b74.jpg" alt="DSC00377" width="375" height="500" /></a></p>
<h2>Google Calendar</h2>
<p>http://forum.xda-developers.com/showpost.php?p=19422673&#038;postcount=60<br />
<a title="下載 GoogleCalendarSyncAdapter.apk" href="http://forum.xda-developers.com/showthread.php?t=944069" target="_blank" rel="noopener">http://forum.xda-developers.com/showthread.php?t=944069</a><br />
也是要放到 /system/app 下, 權限要設成 644, 沒有這個檔案, Google Calendar 沒有辦法下載日曆.<br />
如果之前有玩 Google Music , 也可以照以上 Link 安裝程式, 安裝完 Google Music 就可以用了.</p>
<h2>Exchange E-mail</h2>
<p>很多公司都是用 Exchange 收送 mail.<br />
這部份請下載 Enhance E-mail, 如果你是在偉大的天龍國管轄權內, Enhance email 是要錢的,<br />
各位只好犧牲一下, 去盜版了.</p>
<p>我試了一下, 可以連上 Microsoft online, 並且可以同步 exchange mail 和 Calendar.<br />
這樣一來, 在 kindle Fire 上就可以看到來自 Google Calendar 和 Exchange 上的 Calendar<br />
等開放 Marketing, 我就會來買一套. (還是 VPN 去買就可以了?)<br />
* 要用 <a href="https://market.android.com/details?id=ch.racic.android.marketenabler&amp;feature=search_result" target="_blank" rel="noopener">Marketing Enable </a>將 Sim Card Information 改成 US T-Mobile, 然後再裝<a href="http://forum.xda-developers.com/showthread.php?t=1240344" target="_blank" rel="noopener"> old market</a></p>
<h2>中文輸入</h2>
<p>我是使用 LIME-HD 這個輸入法, 可以在 Google Market 上下載<br />
<a href="http://www.mobile01.com/topicdetail.php?f=605&amp;t=2460016&amp;last=32345343#32183932" target="_blank" rel="noopener">中文輸入修改教學</a><br />
這是 LIME-HD 的字串, 文章內的輸入法代換成這個字串就可以使用了<br />
[TEXT]<br />
com.android.inputmethod.latin/.LatinIME:net.toload.main.hd/.LIMEService<br />
[/TEXT]</p>
<h2>如何 root 6.2.1 Update 過的機器</h2>
<p><span style="color: #ff0000;">再次聲明, 以下動作風險極高, 請自負風險, 謝謝</span></p>
<p>千呼萬喚始出來, 在開始之前, 你必需準備一條叫做 Factory Cable 的 MicroUSB 線材<br />
主要是要將 Pin1 和 Pin4 連結起來, 然後先關機, 插上 Cable 後開機, 就可以進 Fastboot mode.<br />
以後是製作方法.<br />
<a href="http://www.androidbrains.com/index.php/2011/12/03/kindle-fire-bricked/" target="_blank" rel="noopener">如果 Kindle 變磚了要怎麼辦? 用 Factory Cable 進 Fastboot mode </a><br />
<a href="http://www.droidforums.net/forum/droid-labs/146492-how-why-make-your-own-motorola-factory-cable.html#post1527935" target="_blank" rel="noopener">why to make your own Motorola &#8220;Factory Cable&#8221;</a></p>
<p>接下來請去下載 Kindle Fire Utility v.6, 那邊有需要的工具.<br />
<a href="http://forum.xda-developers.com/showthread.php?t=1399889" target="_blank" rel="noopener">Kindle Fire Utility v.6 </a><br />
順便下載 Apps.zip 和 TWRP. TWRP 下載完請放到和 Kindle Fire Utility 下的 tools</p>
<p>到這個地方下載 update-6.2.1-rooted-secureboot.zip<br />
<a href="http://forum.xda-developers.com/showthread.php?t=1402440" target="_blank" rel="noopener">[Update] Pre-rooted stock 6.2.1 update (secure and unsecure boot images)</a><br />
下載完之後, 請將 Apps.zip 和 update-6.2.1-rooted-secureboot.zip 放到 Kindle Fire 內的 KindleUpdate 目錄.</p>
<p>這時請先關機, 再插上改好的 Factory MicroUSB Cable<br />
開機的時候 Windows 會抓到 USB Device , 並且認不到, 這時我們 Kindle Fire Utility 解開來內在 Drivers 的目錄下有 Driver. 更新完 Driver 就可以了.</p>
<p>基本上就是按照這一篇, 按照他的指令 install TWRP<br />
<a href="http://forum.xda-developers.com/showpost.php?p=20555086&amp;postcount=68" target="_blank" rel="noopener">[Update] Pre-rooted stock 6.2.1 update (secure and unsecure boot images)</a></p>
<p>[TEXT]<br />
C:\Kindle Fire Utility\tools&gt;fastboot -i 0x1949 getvar product<br />
=product: kindle<br />
finished. total time: -0.000s<br />
[/TEXT]</p>
<p>確認有連上之後, 再執行以下指令.<br />
[TEXT]<br />
C:\Kindle Fire Utility\tools&gt;fastboot -i 0x1949 boot twrp-blaze-2.0.0RC0.img<br />
downloading &#8216;boot.img&#8217;&#8230; OKAY [ 2.719s]<br />
booting&#8230; OKAY [ 0.004s]<br />
finished. total time: 2.723s</p>
<p>C:\Kindle Fire Utility\tools&gt;fastboot oem idme bootmode 4000[/TEXT]<br />
等待一下, 機器會重開, 就會進入 TWRP 並且 install 完 .</p>
<p>install 完 TWRP 就要重開, 重開完就可以按 Power 鍵進入 TWEP, 選 install .<br />
然後選擇剛剛 copy 到 KindleUpdate 內的 update-6.2.1-rooted-secureboot.zip.<br />
重開進到 Android 後, 再進到 TWRP 再 install app.zip<br />
然後, 然後, 正直和善良都回來了呀 (不, 是 Google Market 和 Gmail 都回來了, 也可以 root 了~~~~)</p>
<p>2011/12/23 10:37 : <del>聽說 one click root 也快出來了.</del></p>
<p>2011/12/24 09:27 : <a href="http://www.youtube.com/watch?v=KapnjR89ICA" target="_blank" rel="noopener">不需要 Factory Cable 也可以 root 的方法</a>, 不過我沒有試, 有興趣的人可以試</p>
<p>2011/12/27 : <a href="http://rootzwiki.com/topic/13027-universal-all-firmware-one-click-root-including-261/" target="_blank" rel="noopener">Universal (All Firmware) One Click Root (Including 2.6.1!)</a><br />
&nbsp;</p>
<h2>其他</h2>
<p>Google Contact 不能用 &#8211; 應該是要用 Amazon 的郵件去下載連絡人<br />
還有很多東西有問題, 不能買的東西還是不能買&#8230;</p>
<p>Kindle Fire 以這個優異的價格, 我覺得我都可以接受這些不便, 只是一般人要入手還是要三思.</p>
<h2>後記</h2>
<p>放一些筆記在這邊</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2011/12/01/1144/kindle-fire-%e9%96%8b%e7%ae%b1%e6%96%87-%e5%8a%a0%e8%b4%88-root-%e6%88%90%e5%8a%9f%e6%96%87/">Kindle Fire 開箱文 (加贈 Root 成功文, 6.2.1 root 文)</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2011/12/01/1144/kindle-fire-%e9%96%8b%e7%ae%b1%e6%96%87-%e5%8a%a0%e8%b4%88-root-%e6%88%90%e5%8a%9f%e6%96%87/feed/</wfw:commentRss>
			<slash:comments>14</slash:comments>
		
		
			</item>
		<item>
		<title>git 筆記: 如何將現有的 Tree 推到 remote</title>
		<link>https://richliu.com/2011/11/01/1133/git-%e7%ad%86%e8%a8%98-%e5%a6%82%e4%bd%95%e5%b0%87%e7%8f%be%e6%9c%89%e7%9a%84-tree-%e6%8e%a8%e5%88%b0-remote/</link>
					<comments>https://richliu.com/2011/11/01/1133/git-%e7%ad%86%e8%a8%98-%e5%a6%82%e4%bd%95%e5%b0%87%e7%8f%be%e6%9c%89%e7%9a%84-tree-%e6%8e%a8%e5%88%b0-remote/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Mon, 31 Oct 2011 17:15:36 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[remote]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1133</guid>

					<description><![CDATA[<p>我本來在開發 AMP 的程式, 所以從 source code clone 了一個新的開發目錄, 稱 A, 再 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2011/11/01/1133/git-%e7%ad%86%e8%a8%98-%e5%a6%82%e4%bd%95%e5%b0%87%e7%8f%be%e6%9c%89%e7%9a%84-tree-%e6%8e%a8%e5%88%b0-remote/">git 筆記: 如何將現有的 Tree 推到 remote</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>我本來在開發 AMP 的程式, 所以從 source code clone 了一個新的開發目錄, 稱 A, 再從 A clone 一個新的開發目錄, 稱 B.<br />
這時在 B 的目錄下, 沒有辦法直接 push 回 A , 因為 A 內有 source code , 所以只好再開一個新的空 git, 往上推. </p>
<p>假設主要的 tracking branch name 是 major. (一般用 origin or master, btw, 我是從別的地方再 clone 過來的, 所以不用此名)<br />
創立一個新的空 git 目錄.<br />
[BASH]<br />
$ cd /data/prj/AMP/core-data<br />
$ git init &#8211;bare<br />
[/BASH]</p>
<p>在 source code A 下, 建立一個新的 remote<br />
[BASH]<br />
$ git remote add test /data/prj/AMP/core-data<br />
$ git push test major<br />
[/BASH]</p>
<p>在 source code B 下, 加入一個新的 remote, 用 git reset &#8211;hard 是清除所有的改變, 以便 pull<br />
[BASH]<br />
$ git diff<br />
$ git reset &#8211;hard<br />
$ git remote add  test /data/prj/AMP/core-data/bare/<br />
$ git pull test major<br />
[/BASH]</p>
<p>* 若是遇到這種情形, 可以檢查是不是這個檔在是 untracked, 可以用 $ git status 查看. 如果是 untracked, 可以刪除.<br />
[BASH]<br />
$ git pull test major<br />
From /data/prj/AMP/core-data/bare<br />
 * branch            major      -> FETCH_HEAD<br />
error: Untracked working tree file &#8216;kernels/linux-2.6.35.12/arch/arm/kernel/real-amp.c&#8217; would be overwritten by merge.  Aborting<br />
[/BASH]</p>
<p>git 功能太多 :-/</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2011/11/01/1133/git-%e7%ad%86%e8%a8%98-%e5%a6%82%e4%bd%95%e5%b0%87%e7%8f%be%e6%9c%89%e7%9a%84-tree-%e6%8e%a8%e5%88%b0-remote/">git 筆記: 如何將現有的 Tree 推到 remote</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2011/11/01/1133/git-%e7%ad%86%e8%a8%98-%e5%a6%82%e4%bd%95%e5%b0%87%e7%8f%be%e6%9c%89%e7%9a%84-tree-%e6%8e%a8%e5%88%b0-remote/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Trace32 Break 的 Condition 指令要如何下.</title>
		<link>https://richliu.com/2011/03/08/1031/trace32-break-%e7%9a%84-condition-%e6%8c%87%e4%bb%a4%e8%a6%81%e5%a6%82%e4%bd%95%e4%b8%8b/</link>
					<comments>https://richliu.com/2011/03/08/1031/trace32-break-%e7%9a%84-condition-%e6%8c%87%e4%bb%a4%e8%a6%81%e5%a6%82%e4%bd%95%e4%b8%8b/#respond</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Tue, 08 Mar 2011 02:44:04 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[break]]></category>
		<category><![CDATA[condition]]></category>
		<category><![CDATA[Trace32]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1031</guid>

					<description><![CDATA[<p>Trace32 的相關內容非常的少, 找都找不到&#8230;. Trace32 在 Break Point  [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2011/03/08/1031/trace32-break-%e7%9a%84-condition-%e6%8c%87%e4%bb%a4%e8%a6%81%e5%a6%82%e4%bd%95%e4%b8%8b/">Trace32 Break 的 Condition 指令要如何下.</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Trace32 的相關內容非常的少, 找都找不到&#8230;.</p>
<p>Trace32 在 Break Point 的地方可以設定 Condition, 這樣就可以設定特定條件停下來.</p>
<p>這邊就是一個範例, 停下來的時候要檢查記憶體的位置 &gt; 200, 記得 /CONDITION 後面的字串中間不能有空白. 要不然會有問題.</p>
<p>[TEXT]<br />
break.set D:0xC02f1e64 /write /ONCHIP /CONDITION data.long(D:0xC02f1e64)>200<br />
[/TEXT]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2011/03/08/1031/trace32-break-%e7%9a%84-condition-%e6%8c%87%e4%bb%a4%e8%a6%81%e5%a6%82%e4%bd%95%e4%b8%8b/">Trace32 Break 的 Condition 指令要如何下.</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2011/03/08/1031/trace32-break-%e7%9a%84-condition-%e6%8c%87%e4%bb%a4%e8%a6%81%e5%a6%82%e4%bd%95%e4%b8%8b/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>程式設計之道 冼鏡光</title>
		<link>https://richliu.com/2011/01/22/1019/%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93-%e5%86%bc%e9%8f%a1%e5%85%89/</link>
					<comments>https://richliu.com/2011/01/22/1019/%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93-%e5%86%bc%e9%8f%a1%e5%85%89/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Sat, 22 Jan 2011 04:26:21 +0000</pubDate>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[哲學]]></category>
		<category><![CDATA[程式設計]]></category>
		<category><![CDATA[道]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=1019</guid>

					<description><![CDATA[<p>大學的時代就看過冼鏡光的這篇文章, 當時覺得很神, 不過文章不知道存在那邊. 現在拜有網路之賜, 到處都找得到 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2011/01/22/1019/%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93-%e5%86%bc%e9%8f%a1%e5%85%89/">程式設計之道 冼鏡光</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>大學的時代就看過冼鏡光的這篇文章, 當時覺得很神, 不過文章不知道存在那邊.</p>
<p>現在拜有網路之賜, 到處都找得到 (所以我也可以 COPY 一下. )</p>
<p>工作了十年, 不管是進銷存, 網路安全, 軟體, 硬體, 軔體都做過. 也碰到神奇的中醫, 在事業不順時也看了莊子</p>
<p>再回頭來看這篇文章, 特別有感覺</p>
<p>程式設計很簡單, 但是要悟程式設計的<strong>道</strong>, 很難.</p>
<p>悟道之前的修行是又多又苦的.</p>
<p><span id="more-1019"></span></p>
<p>THE DAO OF PROGRAMMING Geoffrey James</p>
<p>程式設計之道 冼鏡光</p>
<p>微電腦時代96,97</p>
<p>第一部 寂靜虛無篇</p>
<p>大師如是說:&#8221;學會從程式抓蟲子之後, 就可以畢業了</p>
<p>1.1 節</p>
<p>.寂靜虛無中有奧秘, 不動不靜, 乃程式之源, 吾無以名之, 故稱之為程式設計之道.</p>
<p>.若道至大, 則作業系統至大; 若作業系統至大, 編譯程式亦然; 若編譯程式至大,</p>
<p>則應用程式亦復如是, 是故使用人大悅, 世有和諧存焉.</p>
<p>1.2 節</p>
<p>.程式設計之道無遠弗屆, 雖晨曦微風而返.</p>
<p>.道生機器語言, 機器語言生組譯程式.</p>
<p>.組譯程式生編譯程式, 於是萬餘語言存焉.</p>
<p>.各語言有其目的, 均表達軟體之陰陽; 其在道中亦各得其所.</p>
<p>.但若能避免, 就不要用COBOL 寫程式.</p>
<p>1.3 節</p>
<p>.太初有道, 道生時空, 故時空乃程式設計之陰陽.</p>
<p>.程式員不悟道則時空永不敷使用, 悟道者恒有充份時空完成目標.</p>
<p>1.4 節</p>
<p>.上智程式員聞道而行之, 中智程式員聞道而求之, 下智程式員聞道而笑之.</p>
<p>.若無笑聲則無道矣.</p>
<p>.至高之聲難以聽聞.</p>
<p>.前進就是後退之路; 大智總是晚成; 每一個完美的程式仍有BUG.</p>
<p>.道在所有知識之外.</p>
<p>第二部 古之大師篇</p>
<p>大師如是說:&#8221;三日不寫程式則生命無趣.</p>
<p>2.1 節</p>
<p>.古程式員神秘而深奧, 無以度量其思維, 僅能描述其表象.</p>
<p>.像狐狸涉水般地小心; 像戰場老兵般地警覺; 像未經琢磨的木頭般地璞拙;</p>
<p>像洞中深潭地不透明.</p>
<p>.誰能指出他們心靈中的秘密?</p>
<p>.答案全在道中.</p>
<p>2.2 節</p>
<p>.大師Turing曾經夢到他是一部電腦, 醒後道:</p>
<p>. &#8220;不知是我Turing作夢變成機器, 還是一部機器作夢變成我我Turing.&#8221;</p>
<p>.一家大電腦公司的程式員參加軟體會議後, 向他的經理報告說:&#8221;你知道其他電腦</p>
<p>公司有什麼程式員嗎? 他們不修邊幅, 頭髮長而邋遢, 衣服既舊且皺, 他們破壞</p>
<p>了氣氛, 而且我簡報時老是製造噪音.&#8221;</p>
<p>.經理說:&#8221;我根本就不應該派你參加會議, 這些程式員超然物外, 他們把生命看成無稽,</p>
<p>意外的結合. 他們往來而無藩籬, 為他們的程式而活, 為什們他們一定要受社會積習</p>
<p>的約束?</p>
<p>.他們生活在道中.&#8221;</p>
<p>2.3 節</p>
<p>.生手問大師:&#8221;有一個程式員從不設計, 測試程式, 寫作文獻, 但了解他的人都認為</p>
<p>他是世間最好的程式員. 為什麼?&#8221;</p>
<p>.大師曰:&#8221;這個程式員已充份悟道, 他超越了設計的需要; 系統垮了不會生氣,</p>
<p>而無條件接受這個世界. 他超越了文獻的需要, 他不再計較是否有人看他的程式.</p>
<p>他也超越了測試的需要, 他的每一個程式都圓滿無缺, 清澈, 優雅, 目的自明.</p>
<p>.是的, 他已悟道, 登堂入室.</p>
<p>第三部 設計篇</p>
<p>大師說:&#8221;到測試程式時再回頭修改設計就太遲了.&#8221;</p>
<p>3.1 節</p>
<p>.曾經有人在參觀電腦展每天進門時都向警衛說:&#8221;我是的妙賊, 偷東西的技巧已臻化境,</p>
<p>先告訴你, 我絕不會放過這次展覽.&#8221;</p>
<p>.這段話刺激到警衛, 因為展覽場有好幾百萬元價值的儀器, 所以老是盯這他,</p>
<p>不過卻只看到這個人一個攤位接著一個攤位看, 哼著小曲而已.</p>
<p>.這個人出門的時侯, 警衛把他帶到一旁搜身, 但卻找不到什麼.</p>
<p>.第二天這個人又來了, 而且教訓警衛說:&#8221;昨天我收獲不錯, 不過今天會更佳.&#8221;</p>
<p>所以警衛就更加注意他了, 但是仍然沒有結果.</p>
<p>.最後一天警衛終於忍不住好奇心, 問那個人:&#8221;賊大師, 我給您弄得寢食難安,</p>
<p>您是否以教我, 究竟偷了些什麼?&#8221;</p>
<p>.這個人笑笑, 說:&#8221;我偷的是概念.&#8221;</p>
<p>3.2 節</p>
<p>.從前有一位大師專寫沒有結構化的程式, 一個生手模仿他, 也開始寫沒有結構化的</p>
<p>程式. 當這位生手要求大師評量進展時, 大師卻批評他寫作沒有結構化的程式.</p>
<p>.大師說:&#8221;對大師適用的不一定適合生手, 在能超越結構化之前, 必須先悟道.&#8221;</p>
<p>3.3 節</p>
<p>.某長官問程式員:&#8221;設計會計系統與作業系統, 那一個比較簡單?&#8221;</p>
<p>.程式員說:&#8221;作業系統.&#8221;</p>
<p>.長官發出不相信的驚呼:&#8221;很顯然的, 會計系統不如作業系統複雜&#8221;,他說.</p>
<p>.&#8221; 不!&#8221;程式員回答,&#8221;在設計會計系統時, 程式員是各種不同主意的人之間的橋樑,</p>
<p>這些主意不外乎: 系統要如何作業? 報表型式如何? 要如何迎合稅法?&#8230;等等.</p>
<p>反過來, 作業系統卻不受外界表象的限制; 在設計作業系統時, 程式員尋求人與機器</p>
<p>間最純的和諧, 這就是為什麼作業系統容易設計.&#8221;</p>
<p>.長官點頭微笑稱是:&#8221;但是那一個容易偵錯?&#8221;</p>
<p>.程式員沒有回答.</p>
<p>3.4 節</p>
<p>.經理去見大師, 並且告訴他一套新應用程式文件的需求規格, 問道:&#8221;如果我給你五</p>
<p>個程式員, 要多久才能設計好這個系統?&#8221;</p>
<p>.大師很快回答:&#8221;一年.&#8221;</p>
<p>.&#8221; 但是我們需要馬上用這個系統! 如果我給你十個程式員, 那要多久?&#8221;經理說.</p>
<p>.大師皺眉說:&#8221;這要兩年.&#8221;</p>
<p>.&#8221; 如果我給你一百個程式員呢?&#8221;</p>
<p>.大師聳聳肩:&#8221;這個系統根本作不出來了.&#8221;</p>
<p>第四部 寫作篇</p>
<p>大師如是說:&#8221;寫作良好的程式本身自成天堂, 寫得差的程式本身就是地獄.</p>
<p>4.1 節</p>
<p>.程式要輕靈, 副程式像一串珍珠. 程式的精神與意圖應始終如一, 不多不少;</p>
<p>沒有多餘的迴圈, 也沒有額外的變數, 既不缺少結構, 也不過份笨重.</p>
<p>.程式應該追隨&#8221; 最低驚訝定律&#8221;,這是什麼?</p>
<p>.簡單得很, 使用人對程式的反應是驚訝的機會要愈低愈好.</p>
<p>.程式不管再複雜, 應該以一個整體來作用; 他應該用內部邏輯, 而不是外在的表</p>
<p>象來指導作業.</p>
<p>.如果程式不滿足這些要求, 就會雜亂而易生混淆, 唯一的補救就是重新寫過.</p>
<p>4.2 節</p>
<p>.生手問大師:&#8221;我有一個程式, 有時侯作得很好, 有時侯卻不行; 我一直遵行程式設</p>
<p>計的規律, 但是卻把我弄得很困擾, 其理安在?&#8221;</p>
<p>.大師答曰:&#8221;因為不悟道才會如此, 只有笨蛋才會期望他的同儕有合理的行為,</p>
<p>而你卻對人類生產的機器有所期望?!計算機只模擬了決定論, 只有道才十全十美.</p>
<p>.程式設計的準則還是暫時性的, 只有道才會進入永恒. 所以, 你在開竅前要先思索道.&#8221;</p>
<p>.&#8221; 但我要如何才能知道已經開竅了呢?&#8221;生手問.</p>
<p>.大師回答:&#8221;從此以後, 你的程式都能正確執行.&#8221;</p>
<p>4.3 節</p>
<p>.大師對弟子說:&#8221;不論軟體之為大為小, 道在所有軟體中.&#8221;</p>
<p>.&#8221; 桌上型計算機有道嗎?&#8221;弟子問.</p>
<p>.&#8221; 有!&#8221;大師答.</p>
<p>.&#8221; 電動玩具程式中有道嗎?&#8221;弟子續問.</p>
<p>.&#8221; 也有!&#8221;大師說.</p>
<p>.&#8221; 那個人電腦的DOS 中有道嗎?&#8221;</p>
<p>.大師咳一下, 輕輕挪動了位置,&#8221;下課&#8221;,他說.</p>
<p>4.4 節</p>
<p>.皇太子的程式員正在寫作軟體, 指尖在鍵盤上飛舞, 程式順暢無誤的編譯完成,</p>
<p>執行起來像陣微風輕拂而完美的結束.</p>
<p>.&#8221; 了不起!&#8221;, 太子嘆曰:&#8221;你的技巧無懈可擊.&#8221;</p>
<p>.&#8221; 技巧?&#8221;程式員從終端機上轉過頭說,&#8221;我所信從的是道, 道超越任何技巧!</p>
<p>我開始學寫程式時, 在我眼前所見是混成一片的程式; 三年後, 不再見到這一大片</p>
<p>程式了</p>
<p>, 我學會使用副程式; 現在, 眼前一片空靈, 什麼都沒有了, 所有東西都進入無</p>
<p>型式的一片靜寂; 所有感覺都不必作用.</p>
<p>.我的精神可以依直覺而不必依任何計劃行事, 換言之, 我的程式自己寫作自己.</p>
<p>當然, 有時會有困難的問題; 我看著他們到來, 我降低自已的速度, 靜靜的看,</p>
<p>改一列程式之後困難就會煙消雲散; 我再重新靜靜坐著欣賞工作的歡樂. 我閉上雙眼</p>
<p>一會兒, 然後關機.&#8221;</p>
<p>.皇太子說:&#8221;我的所有程式員都那麼聰明睿智嗎?&#8221;</p>
<p>第五部 維護篇</p>
<p>大師如是說:&#8221;雖然程式只有三列, 但總有一天需要維護.&#8221;</p>
<p>5.1 節</p>
<p>.常用的門不必上油.</p>
<p>.急流不會淤塞.</p>
<p>.聲音與思想不能在真空中傳遞.</p>
<p>.不用的軟體會生鏽.</p>
<p>.這就是至大的奧秘.</p>
<p>5.2 節</p>
<p>.經理問程式員究竟要多久才能把手上的程式寫完.&#8221;明天&#8221;,程式員很快的回答.</p>
<p>.經理說:&#8221;我想你不太踏實; 真的要多久?&#8221;</p>
<p>.程式員想了一會兒:&#8221;我希望在程式中加上一些東西, 這至少要兩週.&#8221;程式員終於說</p>
<p>.&#8221; 時間還是短了一些&#8221;,經理堅持說:&#8221;如果你能簡單的告訴我什麼時後能寫完我才會滿意.&#8221;</p>
<p>.程式員同意這一點.</p>
<p>.幾年後經理退休了, 在歡送餐會上發現那個程式員伏在終端機上睡著了, 因為他</p>
<p>寫程式寫了整夜.</p>
<p>5.3 節</p>
<p>.一個生手被分派去寫一個單純的財務軟體.</p>
<p>.這個生手狂熱地工做了幾天, 但是當大師看他的成品時, 卻發現這個程式中包</p>
<p>含一個螢光幕編修程式, 一組一般性的繪圖程式, 一個人工智慧界面, 但卻沒有什麼</p>
<p>與財務方面有關.</p>
<p>.大師就問他, 這個生手卻變得很激動:&#8221;不要那麼沒耐心,&#8221;他說,&#8221;我最終會把財務</p>
<p>部份加上去.&#8221;</p>
<p>5.4 節</p>
<p>.好農夫會忽視他種的穀子嗎?</p>
<p>.好老師會忽略他最差的學生嗎?</p>
<p>.好父親會容許他的孩子挨餓嗎?</p>
<p>.好程式員會拒絕維護自己的程式嗎?</p>
<p>第六部 管理篇</p>
<p>大師如是說:&#8221;程式員要多, 經理要少, 生產力就會增加.&#8221;</p>
<p>6.1 節</p>
<p>.經理有開不完的會的話, 程式員就會寫電玩; 主計部門想到利潤, 發展經費</p>
<p>就會被刪減; 高級科學家談到藍藍青天, 那麼青天一定會有浮雲飛過.</p>
<p>.當然, 這不是程式設計之道.</p>
<p>.當經理許下承諾, 程式員就不理會電玩; 當主計部門有長程規劃, 就會回復</p>
<p>和諧與秩序; 當高級科學家處理手上的問題, 問題很快就會解決.</p>
<p>.這才是程式設計之道.</p>
<p>6.2 節</p>
<p>.為什麼程式員沒有生產力? 因為他們的時間都花在開會上頭.</p>
<p>.為什麼程式員難以駕御? 因為管理階層干預太多.</p>
<p>.為什麼程式員一個接一個辭職? 因為他們精力耗光了.</p>
<p>.在不良管理下工作, 程式員不會覺得他的工作有價值.</p>
<p>6.3 節</p>
<p>.某個經理快被炒魷魚了, 但是他底下的一個程式員寫了一個叫好又叫座的程式;</p>
<p>當然, 這位經理因而保住了飯碗.</p>
<p>.經理打算給這位程式員一點獎勵, 但他拒絕接受, 並且說:&#8221;因為我覺得這是個有</p>
<p>趣的概念, 才會寫這個程式, 所以我不希望有獎勵.&#8221;</p>
<p>.經理聽了之後說:&#8221;這個程式員雖然職位不高, 但卻充份了解做為一個職員的責任,</p>
<p>讓我們把他升成崇高的管理顧問吧!&#8221;</p>
<p>.在告訴程式員時, 他再度拒絕, 說:&#8221;我之存在是因為可以寫程式, 如果升了我,</p>
<p>那除了浪費每一個人的時間外而成不了事. 我可以走了嗎? 我還得寫程式.&#8221;</p>
<p>6.4 節</p>
<p>.經理告訴程式員們說:&#8221;下面是你們的工作時間: 早上九點來上班, 下午五點鐘下班.&#8221;</p>
<p>所有程式員都很生氣, 有幾個馬上辭職.</p>
<p>.於是經理說:&#8221;好吧! 這樣好了, 只要能夠如期完工, 工作時間由你們自定.&#8221;程式員現</p>
<p>在滿意了, 每天中午開始工作, 直到第二天早上.</p>
<p>第七部 公司智慧篇</p>
<p>大師如是說:&#8221;你可以對主管示範一個程式, 但無法讓他通曉電腦.&#8221;</p>
<p>7.1 節</p>
<p>.生手問大師:&#8221;遙遠東方有一個叫&#8221; 公司總部&#8221; 的偉大樹狀結構, 上面滿滿地標上了</p>
<p>些副總裁, 會計長等的圖案. 它發出大量的備忘錄, 每張上面都寫了&#8221; 收文!&#8221;</p>
<p>&#8221; 發文!&#8221;沒有人知道是什麼意義. 每年都會把新的名字加到新的分 枝上, 但似乎全</p>
<p>都徒勞無功. 為什麼這樣一個不自然的組織還能繼續存在?&#8221;</p>
<p>.大師回答說:&#8221;你已經體認到這個龐大的結構, 而被它不合理的目的困擾.</p>
<p>不過你能不從它無休止的迴旋而得到樂趣嗎? 能夠不欣賞深藏在枝葉底端毫無困難</p>
<p>的程式設計嗎? 為什麼要被他的無用而困擾呢.&#8221;</p>
<p>7.2 節</p>
<p>.東方海上有大魚曰鯤, 鯤能變成雙翼遮天的大鵬. 當大鵬飛越陸地時帶來一道公司</p>
<p>總部的訊息, 這道訊息正好掉在一群程式員中央, 然後大鵬折起雙翼乘風而歸.</p>
<p>.生手程式員瞪眼望著大鵬, 因為他們不認得; 中智程式員憂大鵬的來臨, 因為他們</p>
<p>害怕它帶來的訊息; 只有大師才能繼續坐在終端機前工作, 因為他不知大鵬的來去</p>
<p>7.3 節</p>
<p>.象牙塔的魔術師帶著他的最新發明去見大師, 他推了一個大黑盒子走進大師的辦公室,</p>
<p>大師正在靜靜的等著.</p>
<p>.&#8221; 這是一套整合性, 分散式, 一般用途的工作站&#8221;,魔術師如是說,&#8221;還有一套專屬的</p>
<p>作業系統, 第六代語言, 多項最先進的使用人界面, 再加上人體工學的設計;</p>
<p>這花了我的助手們好幾百人年才造出來的, 不是很了不起嗎?&#8221;</p>
<p>.大師抬了下眼珠子,&#8221;的確了不起.&#8221;大師說.</p>
<p>.魔術師繼續說:&#8221;公司總部已經下令每個人都要用這台工作站做發展新軟體的基石,</p>
<p>您同意嗎?&#8221;</p>
<p>.&#8221; 當然.&#8221;大師答道:&#8221;我馬上會把它放到資訊中心去.&#8221;於是魔術師高高興興的回到</p>
<p>象牙塔去.</p>
<p>.幾天後, 一個生手在大師的辦公室裡團團轉, 說:&#8221;我找不到新程式的報表,</p>
<p>您知道會在那兒嗎?&#8221;</p>
<p>.&#8221; 當然&#8221;,大師答道,&#8221;報表就堆在資訊中心裡頭的基石上!&#8221;</p>
<p>7.4 節</p>
<p>.大師可以毫無憂慮的從這個程式轉入另一個程式, 管理上的改變傷不到他;</p>
<p>縱使計劃中止了, 也不會被炒魷魚. 為什麼? 因為他充滿了道.</p>
<p>第八部 硬體與軟體篇</p>
<p>大師如是說:&#8221;沒有風, 草不會動, 沒有軟體, 硬體就是廢物.&#8221;</p>
<p>8.1 節</p>
<p>.生手問大師:&#8221;我知道一家電腦公司比其他的大得多, 高高在上就像巨人之比侏儒;</p>
<p>它的任一部都可以單獨成為一個企業. 為什麼會這樣?&#8221;</p>
<p>.大師回答:&#8221;你為什麼問這個笨問題? 這家公司就是因為它大才會這麼大. 如果它只</p>
<p>知道硬體, 沒有人會買它; 如果只生產軟體, 沒有人會用它; 如果只維護系統,</p>
<p>人家會把它看成修理員; 但是因為他把所有的合在一起, 人們就把它當神一樣看待了</p>
<p>. 它根本無需競爭, 因為贏來不費吹灰之力.&#8221;</p>
<p>8.2 節</p>
<p>.大師有一天經過一個生手旁邊, 發現生手迷上一台手掌型的電玩,&#8221;對不起&#8221;,大師說,</p>
<p>&#8220;我可以看看它嗎?&#8221;</p>
<p>.生手停下來, 並且把這台機器交給大師. 大師說:&#8221;我看到這台機器玩起來有三個層次:</p>
<p>初級, 中級, 高級; 不過這種機器通常都有另一個層次的說法, 使機器贏不了人類,</p>
<p>而人類也勝不了機器.&#8221;</p>
<p>.&#8221; 啊! 大師&#8221;,生手說:&#8221;這個奇妙的開關在那裡?&#8221;</p>
<p>.大師把機器摔到地上, 用腳把它踏爛.</p>
<p>.突然地, 生手開竅了.</p>
<p>8.3 節</p>
<p>.從前有一位微電腦的程式員對一位來拜訪他的大型電腦程式員說:&#8221;你看,</p>
<p>在我這兒多好! 我有我自己的作業系統與案儲存設備, 我不必與任何人共用任</p>
<p>何電腦資源;軟體本身自給自足, 而且容易使用. 為什麼你不辭掉目前的工作</p>
<p>來加入我們?&#8221;</p>
<p>.於是大型電腦的程式員就對他的朋友解釋:&#8221;大型電腦就像古之聖哲般的穩穩座落i</p>
<p>在資訊中心中央, 磁碟一個接一個蔚為奇觀, 軟體像鑽石般地有多種面目, 像</p>
<p>古森林般的濃密茂盛. 各個程式像一片急流般地湧入系統, 而這就是我在那兒工</p>
<p>作的樂趣 .&#8221;</p>
<p>.聽了這段話之後, 微電腦程式員靜默無聲; 但是這兩個人卻結為好友, 至死不渝.</p>
<p>8.4 節</p>
<p>.Hardware與Software走在路上, Software說:&#8221;你是陰我是陽, 如果我們能一條心,</p>
<p>一定會成大名賺大錢.&#8221;所以,他們就聯合在一起而想征服世界.</p>
<p>.走了一段路之後, 碰到Firmware, 穿得破破爛爛, 拿著根柺杖, 並且對他們說:</p>
<p>&#8220;道在陰陽之外, 寂靜不動如古井之不生波瀾; 道不求名, 故無人知曉其存在;</p>
<p>道不逐利, 因它圓滿無缺. 道超乎時空之外.&#8221;</p>
<p>.Hardware和Software聽了之後倍感慚愧而打道回家.</p>
<p>第九部 尾聲</p>
<p>大師如是說:&#8221;這是下課的時候了!&#8221;</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2011/01/22/1019/%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93-%e5%86%bc%e9%8f%a1%e5%85%89/">程式設計之道 冼鏡光</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2011/01/22/1019/%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93-%e5%86%bc%e9%8f%a1%e5%85%89/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Android Dev Phone 升級 Eclair (2.1)</title>
		<link>https://richliu.com/2010/04/30/917/android-dev-phone-%e5%8d%87%e7%b4%9a-eclair-2-1/</link>
					<comments>https://richliu.com/2010/04/30/917/android-dev-phone-%e5%8d%87%e7%b4%9a-eclair-2-1/#comments</comments>
		
		<dc:creator><![CDATA[richliu]]></dc:creator>
		<pubDate>Fri, 30 Apr 2010 12:20:11 +0000</pubDate>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[adp]]></category>
		<category><![CDATA[Eclair]]></category>
		<category><![CDATA[HTC Magic]]></category>
		<category><![CDATA[recovery]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[T-Mobile G1]]></category>
		<category><![CDATA[upgrade]]></category>
		<category><![CDATA[升級]]></category>
		<guid isPermaLink="false">https://richliu.com/?p=917</guid>

					<description><![CDATA[<p>其實 Android 升級也不是像想像中麻煩, 但是升級之前需要做很多準備工作, 如果不是熟門熟路的話, 會不 [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://richliu.com/2010/04/30/917/android-dev-phone-%e5%8d%87%e7%b4%9a-eclair-2-1/">Android Dev Phone 升級 Eclair (2.1)</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>其實 Android 升級也不是像想像中麻煩, 但是升級之前需要做很多準備工作, 如果不是熟門熟路的話, 會不知道在做什麼, 但是如果熟悉了以後, 換 ROM 大概就像喝水一樣容易 .</p>
<p>以下就是我花一堆時間升級得到的心得. 希望對大家有用</p>
<p>本文章僅適用於 ADP1 (Android Dev Phone 1), 其他不適合.<br />
其他相同的機型有 HTC Magic 和 T-Mobile G1</p>
<p><span style="color: #ff0000;"><strong>* 免責聲明: 任何改機行為皆有極大風險, 請自負風險, 本人不負任何責任 *</strong></span></p>
<h1><span id="more-917"></span>名詞解釋</h1>
<p>先知道名詞是很重要的, 要不然連 Keyword 都 Search 不到 :p</p>
<h3>IPL: Initial Program Loader</h3>
<p>為一個小的 Loader, 主要負責 initial DRAM, CPU 等, 找到的資料有說到 SPL 刷死掉了以後, 可以靠 IPL 救.<br />
不過這看起來要拆機了.</p>
<h3>SPL : Second Program Loader</h3>
<p>在 IPL 之後載入的 Loader. Loader 的角色有點像是 PC 的 Bios<br />
SPL 可以燒 nbh(應該是每台機器的 key, 開發機不需要去弄這個), 提供 Fastboot 更新介面(等一下會提)<br />
更新 SPL 風險是非常高的, 請確定你的手機型號之後再更新<br />
進入 SPL 的方法, 關機時, 按住 camera + Power 鍵(掛電話鍵) 就可以進入 SPL</p>
<h3>Fastboot:</h3>
<p>進入 SPL 後, 可以切至 Fastboot mode, 可以透過 USB + Fastboot 的程式更新特定區域的 image .<br />
這是當 Recovery 不能用的時候, 拿來緊急救援用的.</p>
<h3>Recovery:</h3>
<p><a title="recovery" href="http://www.flickr.com/photos/richliu_tw/4565377896/" target="_blank" rel="noopener"><img loading="lazy" decoding="async" title="recovery" src="http://farm4.static.flickr.com/3479/4565377896_e0bd1c2330.jpg" alt="recovery" width="358" height="500" /></a><br />
系統提供一個 Recovery mode, 這個 Recovery 是一個簡化的 Linux 系統, 內含一個 busybox 及其他的 tool<br />
主要是用來更新 ROM 及其他開發者提供的功能. 像是 SPL 也是可以從 Recovery 內救.<br />
以我目前使用的 RA-Dream 來說, 支援以下的功能</p>
<ul>
<li>Reboot</li>
<li>Goto Console</li>
<li>USB-MS (摸擬成一個 USB Mass Storage, 就是讓 Android 變成 USB Flash 模式.</li>
<li>Backup/Restore : nandroid, 可以備份/回復 Nand, 常常換系統者必備.</li>
<li>Flash Zip from SD (這功能就是可以更新大部份的 ROM 了)</li>
<li>Wipe : 清除資料</li>
<li>Partition SDCard : 現在有的 ROM 支援 APP2SD, 尤其是 Eclair (2.1) 的系統一定要 APP2SD 才可以使用.</li>
<li>Shutdown</li>
</ul>
<p>幾乎所有燒機的功能都包含在內了, 之前可能會有人找到 cm-recovery-1.4, 不過那個功能比 RA-Dream 差太多了.</p>
<p>進入 Recovery 的方法, Home + Power On Key.</p>
<h3>RADIO:</h3>
<p>這一般指的是 GSM 部份的 Radio Code. 因為 GSM 都是自己跑一部份專有的 Code.</p>
<h3>ROM:</h3>
<p>通常講到 ROM 都是講到 Android 主系統, HTC 有協助 Google 開發系統, 也有很多第三方放出來的 ROM 可以用, 如果很愛刷 ROM 換系統, 或是自己 compile 都是可行的</p>
<p>第三方比較有名的有</p>
<p>2.1</p>
<ul>
<li><a id="thread_title_672992" href="http://forum.xda-developers.com/showthread.php?t=672992" target="_blank" rel="noopener">[ROM] CyanogenMod-5 &#8211;  Would you like a pony? (EXPERIMENTAL) [04/29 &#8211; v5.0.7-test1]</a></li>
<li><a id="thread_title_642643" href="http://forum.xda-developers.com/showthread.php?t=642643" target="_blank" rel="noopener">[ROM] [v1.2] [OPTIMIZED] KiNgxKxKlair  DroidEris2G1 {4/9/10 1:59 pm PST}</a></li>
<li> <a id="thread_title_633957" href="http://forum.xda-developers.com/showthread.php?t=633957" target="_blank" rel="noopener">[UPDATE][ROM]CaNNoN202 Complete Eclair  [v2.0](Almost Complete)[4/2/10]-[FAST][STABLE]</a></li>
</ul>
<p>1.6</p>
<ul>
<li><a id="thread_title_567610" href="http://forum.xda-developers.com/showthread.php?t=567610" target="_blank" rel="noopener">[ROM] CyanogenMod &#8211; No, you can&#8217;t have a pony  (STABLE) [UPDATED 03/04 &#8211; v4.2.15.1]</a></li>
<li><a id="thread_title_613809" href="http://forum.xda-developers.com/showthread.php?t=613809" target="_blank" rel="noopener">[ROM]Super  D 1.11  &#8220;Rehab is for Quitters&#8221; (4/28)</a></li>
</ul>
<h3>APP2SD:</h3>
<p>ADP1 的 Flash 只有 192MByte, 所以放 Application 不太夠, 所以大家就將腦筋動到 SD Card 上.<br />
這個功能就叫 APP2SD. 在 Linux 下不過就只是一個 shell script.</p>
<p>早期 APP2SD 要自己弄,<br />
現在新的 ROM 都支援 APP2SD, 更新的 2.1 都一定要啟動 APP2SD 才能使用</p>
<p>有了這些基礎知識以後, 接下來就是準備開始動手了.</p>
<p><span style="color: #ff0000;"><strong>*  免責聲明: 任何改機行為皆有極大風險, 請自負風險, 本人不負任何責任 *</strong></span></p>
<h2>準備</h2>
<ul>
<li>PC</li>
<li>USB cable</li>
<li><a href="http://developer.android.com/sdk/index.html" target="_blank" rel="noopener">Android SDK</a></li>
<li><a href="http://developer.htc.com/adp.html" target="_blank" rel="noopener">fastboot </a></li>
</ul>
<p>Android SDK 提供了 adb shell command 的功能 (要啟動到 recovery)<br />
fastboot 提供了在 SPL 狀況下可以更新 image 的機會.</p>
<h2>更新 Recovery.img</h2>
<p>我個人喜歡用 <a href="http://forum.xda-developers.com/showpost.php?p=4647751&amp;postcount=1" target="_blank" rel="noopener">RA-Dream</a> 先下載 <a href="http://rapidshare.com/files/357127614/recovery-RA-dream-v1.6.2.img" target="_blank" rel="noopener">recovery-RA-dream-v1.6.2.img</a> 然後存到 SDCard 內.</p>
<p>重開機按 Home + Power On 進入 recovery mode.</p>
<p>在 PC 端進入 adb mode</p>
<p>[shell]<br />
# adb shell<br />
切至 ADP<br />
$ su<br />
# mount -a<br />
# flash_image recovery /sdcard/recovery-RA-dream-v1.6.2.img</p>
<p>[/shell]</p>
<p>如果要用 Fastboot 升級也是可以, 但是要先更新 SPL. 那更麻煩&#8230;..</p>
<p>[shell]<br />
# fastboot devices (確認 devices)<br />
# fastboot flash recovery recovery-RA-dream-v1.6.2.img<br />
[/shell]</p>
<h2>更新 Radio Image</h2>
<p>如果不是 2.22.19_26I, 請更新你的 Radio Image, 可以啟動進 SPL 看一下現在的版本</p>
<p>可以從 HTC 下載 <a href="http://developer.htc.com/adp.html" target="_blank" rel="noopener">2.22.19_26I</a>, <a href="http://code.google.com/p/sapphire-port-dream/" target="_blank" rel="noopener">sapphire-port-dream</a> 也有一份 <a href="http://code.google.com/p/sapphire-port-dream/" target="_blank" rel="noopener"></a></p>
<p><a title="ota-radio-1_22_14_11.zip" onclick="DisplayDialogAndAcceptDownload('aHR0cDovL21lbWJlci5hbWVyaWNhLmh0Yy5jb20vZG93bmxvYWQvUm9tQ29kZS9BRFAvb3RhLXJhZGlvLTJfMjJfMTlfMjZJLnppcA==','io_device_license.htm','You  must agree to the License to download the file.');" href="javascript:void(0);">ota-radio-2_22_19_26I.zip</a> 下載之後放到 SDCard 內, 然後重開機進入 Recovery mode.<br />
如果這邊更新 Ra-dream recovery.img 己經成功了, 那就可以直接進 Recovery Mode, 切進 USB-MS mode, 就會變成 Mass Storage, 可以直接從電腦傳檔案進去.<br />
用 flash zip from SD 的功能, 就會列出來, 直接選擇就可以.<br />
解壓完重開機即可.</p>
<p><strong>這就是我愛用 Ra-dream recovery.img 的原因 XD</strong></p>
<h2>更新 SPL</h2>
<p>第一件事情就是要確認機器的版本, 這是一張 SPL 的圖案, 這是改過的<br />
<a title="SPL" href="http://www.flickr.com/photos/richliu_tw/4565377486/" target="_blank" rel="noopener"><img loading="lazy" decoding="async" title="SPL" src="http://farm4.static.flickr.com/3334/4565377486_a34048c358.jpg" alt="SPL" width="339" height="500" /></a></p>
<p>[text]<br />
DREAM PVT 32B ENG S-OFF<br />
HBOOT-1.33.2005 (DREA10000)<br />
CPLD-4<br />
RADIO-2.22.19.26I<br />
[/text]<br />
第一行是 PVT 32B 是代表這隻是 Google ADP1 (Dream/Tmobile G1)<br />
第二行是目前 SPL 的版本, DREA***** 英國, DREA10000 美國, DREA11000 歐洲<br />
第四行是 Radio 的版本<br />
更新完 SPL 就可以裝第三方的 Android ROM, 但是 HTC 版的就不能用了. 如果要用, 就要降級</p>
<p>以下是更多的說明</p>
<blockquote><p>SPL Info<br />
&#8211; The G or H at the end identify if it&#8217;s a Google or HTC SPL<br />
&#8211; ENG : Engineering version<br />
&#8211; SHIP : Shipment version<br />
&#8211; DEV : Development version (ION)<br />
&#8211; S-off and S-on : Security on and off (writing directly to nand or not) , most probably not SPL linked.<br />
&#8211; PVT 32A : 288MB RAM / Qualcomm MSM7200a<br />
&#8211; PVT 32B : 192MB RAM / Qualcomm MSM7201a<br />
&#8211; CPLD XX : What does this mean?</p></blockquote>
<p>我目前是使用 <a href="http://code.google.com/p/sapphire-port-dream/" target="_blank" rel="noopener">Danger SPL</a></p>
<p>下載後丟到 SD Card, 進入 Recovery Mode, 然後用 Flash zip from SD card 就可以.</p>
<h2>備份系統</h2>
<p>當然我就會講, 進入 Recovery Mode, 選 Backup/Restore 的功能, 選 NAND Backup 即可.<br />
(其實我是沒有在 backup 的 (爆))</p>
<h2>規劃 SDcard</h2>
<p>我選用的這一版 Recovery 有 Partition SD Card 的功能</p>
<p>但是我當時是用 Linux 去預先規劃, 以我 2G SD Card 為例</p>
<p>Partition 1 : FAT32 :  1.4GByte<br />
Partition 2: ext3 : 500MByte<br />
Partition 3: Linux Swap : 96MBytes</p>
<p>Partition 2 也可以選用比較新的 ext4, 不過這就要比較新版的 ROM 才支援這個功能, 一般來說, 使用 ext3 是支援度最廣的.</p>
<h2>升級 ROM</h2>
<p>接下來就是下載 ROM 了.<br />
以 2.1 為例</p>
<p>2.1</p>
<ul>
<li><a id="thread_title_672992" href="http://forum.xda-developers.com/showthread.php?t=672992" target="_blank" rel="noopener">[ROM]  CyanogenMod-5 &#8211;  Would you like a pony? (EXPERIMENTAL) [04/29 &#8211;  v5.0.7-test1]</a></li>
<li><a id="thread_title_642643" href="http://forum.xda-developers.com/showthread.php?t=642643" target="_blank" rel="noopener">[ROM]  [v1.2] [OPTIMIZED] KiNgxKxKlair  DroidEris2G1 {4/9/10 1:59 pm PST}</a></li>
<li> <a id="thread_title_633957" href="http://forum.xda-developers.com/showthread.php?t=633957" target="_blank" rel="noopener">[UPDATE][ROM]CaNNoN202  Complete Eclair  [v2.0](Almost Complete)[4/2/10]-[FAST][STABLE]</a></li>
</ul>
<p>點進去後找到 ROM 下載, 丟到 SDCard 內</p>
<p>然後選 flash zip from SD.</p>
<p>以 CyanogenMod-5 為例, 會下載<br />
update-cm-5.0.7-DS-test1-signed.zip<br />
gapps-ds-ERE36B-signed.zip<br />
丟進去一起 Flash zip from SD 就好了, 如果是從 1.5/1.6 升級上來, 那記得先 wipe data. 這樣比較不會出問題.</p>
<p>如果是 2.1 的話, 第一次啟動可能需要 5~15 分鐘, 需要耐心等候.</p>
<p>有了 RA-Dream 省了很多事情, 所有的動作都可以 Flash zip from SD.<br />
而新的 ROM 都支援 APP2SD. 所以很多網路上的文件都不太適用了.</p>
<p>然後這麼方便的結果就是 ROM 一直換一直換&#8230;..</p>
<p>目前用到 CaNNoN202 這個不錯, CyanogenMod-5 也可以.</p>
<p>KiNgxsKxKlair功能很強, 但是問題很多, 連 Google Applications 都啟動不了.<br />
不過可以看一下 HTC Legend(?) 大概的樣子是長得什麼樣. 我覺得很炫就是了 <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>目前的缺點就是..<br />
我的 Camera 不知道為什麼都沒有辦法再使用了, 不知道是 Hardware 的問題還是 Software 的問題.<br />
不過之前 ADP1 早就被我玩爛了(大概是自己編kernel的關係), 所以這也不是缺點了 (默)&#8230;</p>
<p>Ref.</p>
<ul>
<li><a href="http://android-dls.com/wiki/index.php?title=Android_FAQ#Q:_What_is_an_SPL.3F" target="_blank" rel="noopener">What is SPL</a></li>
<li><a href="http://www.cnpda.com.cn/thread-322768-1-1.html" target="_blank" rel="noopener">[教 程] [G2]SPL/RADIO/RECOVERY/ROM 专用名词说明</a></li>
<li><a href="http://www.androidin.net/bbs/thread-15742-1-1.html" target="_blank" rel="noopener">【乐教：新人教程】完全刷机教程！</a></li>
<li><a href="http://forum.xda-developers.com" target="_blank" rel="noopener">http://forum.xda-developers.com (必看, 很多文件都是從這邊出來的)</a></li>
</ul>
<p>The post <a rel="nofollow" href="https://richliu.com/2010/04/30/917/android-dev-phone-%e5%8d%87%e7%b4%9a-eclair-2-1/">Android Dev Phone 升級 Eclair (2.1)</a> appeared first on <a rel="nofollow" href="https://richliu.com">richliu&#039;s blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://richliu.com/2010/04/30/917/android-dev-phone-%e5%8d%87%e7%b4%9a-eclair-2-1/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
