<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>even629</title>
  <icon>https://even629.com/en/icon.png</icon>
  <subtitle>blog</subtitle>
  <link href="https://even629.com/en/atom.xml" rel="self"/>
  
  <link href="https://even629.com/en/"/>
  <updated>2025-03-14T13:31:13.000Z</updated>
  <id>https://even629.com/en/</id>
  
  <author>
    <name>even629</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>RustDesk Remote Desktop Self-Hosted Server</title>
    <link href="https://even629.com/en/posts/42858/"/>
    <id>https://even629.com/en/posts/42858/</id>
    <published>2025-03-14T13:12:13.000Z</published>
    <updated>2025-03-14T13:31:13.000Z</updated>
    
    <content type="html"><![CDATA[<div class="timeline blue"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>Timeline</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2025-03-14</p></div></div><div class='timeline-item-content'><ol><li>init</li></ol></div></div></div><hr><p>After using ToDesk for a few days, since it was not shut down(I prefer to leaving the computer open), the free quota was used up in the middle of the month, and I could no longer continue using it for free. I uninstalled it and switched to RustDesk, it really astonished me, using Self-host, which is free and offers much higher frame rates and resolution than ToDesk’s free version. Below is the setup log.</p><h1 id="Basic-Environment-Setup"><a href="#Basic-Environment-Setup" class="headerlink" title="Basic Environment Setup"></a>Basic Environment Setup</h1><p>I am using two Windows (win10) and one Ubuntu (with the configuration shown below). The Ubuntu server acts as the ID&#x2F;relay server, allowing one Windows machine to connect to another. Ubuntu needs Docker installed, and both Windows machines need to install RustDesk and perform some configuration.</p><div class="tip warning faa-horizontal animated"><p>My three machines are all in the same local area network (LAN)</p></div><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/pc_environment.png" alt="Hardware Environment" loading="lazy"></p><h2 id="Installing-Docker-and-Docker-Compose-Plugin"><a href="#Installing-Docker-and-Docker-Compose-Plugin" class="headerlink" title="Installing Docker and Docker Compose Plugin"></a>Installing Docker and Docker Compose Plugin</h2><p>Reference:<br>   <div class="tag link"><a class="link-card" title="Installing Docker on Ubuntu" href="https://docs.docker.com/engine/install/ubuntu/"><div class="left"><img src="https://docs.docker.com/favicons/docs@2x.ico"/></div><div class="right"><p class="text">Installing Docker on Ubuntu</p><p class="url">https://docs.docker.com/engine/install/ubuntu/</p></div></a></div><br>Once installation is complete, add the current user to the Docker group:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Add docker user group, it should already exist</span></span><br><span class="line"><span class="built_in">sudo</span> groupadd docker</span><br><span class="line"><span class="comment"># Add the current user to the docker group</span></span><br><span class="line"><span class="built_in">sudo</span> gpasswd -a <span class="variable">$USER</span> docker</span><br><span class="line"><span class="comment"># Update the user group</span></span><br><span class="line">newgrp docker</span><br><span class="line">docker version</span><br></pre></td></tr></table></figure><h2 id="docker-compose-yaml"><a href="#docker-compose-yaml" class="headerlink" title="docker-compose.yaml"></a>docker-compose.yaml</h2><p>Reference the official documentation：<br>   <div class="tag link"><a class="link-card" title="RustDesk Self-Hosted Server" href="https://rustdesk.com/docs/en/self-host/rustdesk-server-oss/docker/"><div class="left"><img src="https://rustdesk.com/docs/images/favicon.png"/></div><div class="right"><p class="text">RustDesk Self-Hosted Server</p><p class="url">https://rustdesk.com/docs/en/self-host/rustdesk-server-oss/docker/</p></div></a></div></p><p>If you have ufw enabled, you need to open these ports:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> ufw status</span><br><span class="line"><span class="built_in">sudo</span> ufw allow 21114:21119/tcp</span><br><span class="line"><span class="built_in">sudo</span> ufw allow 8000/tcp</span><br><span class="line"><span class="built_in">sudo</span> ufw allow 21116/udp</span><br></pre></td></tr></table></figure><p>Choose a directory to store the ID&#x2F;relay server data:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> -p ~/rustdesk</span><br><span class="line"><span class="built_in">cd</span> ~/rustdesk</span><br><span class="line"><span class="built_in">touch</span> docker-compose.yaml</span><br></pre></td></tr></table></figure><p>Here is the docker-compose.yaml file from the official RustDesk documentation:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">hbbs:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">hbbs</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">rustdesk/rustdesk-server:latest</span></span><br><span class="line">    <span class="attr">command:</span> <span class="string">hbbs</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data:/root</span></span><br><span class="line">    <span class="attr">network_mode:</span> <span class="string">&quot;host&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">hbbr</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">hbbr:</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">hbbr</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">rustdesk/rustdesk-server:latest</span></span><br><span class="line">    <span class="attr">command:</span> <span class="string">hbbr</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data:/root</span></span><br><span class="line">    <span class="attr">network_mode:</span> <span class="string">&quot;host&quot;</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br></pre></td></tr></table></figure><p>Then start it.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">docker compose up -d</span><br><span class="line"><span class="comment"># Go to ~/rustdesk/data directory</span></span><br><span class="line"><span class="built_in">cd</span> data</span><br><span class="line"><span class="comment"># View the key</span></span><br><span class="line"><span class="built_in">cat</span> id_*.pub</span><br></pre></td></tr></table></figure><h2 id="Installing-and-Configuring-RustDesk"><a href="#Installing-and-Configuring-RustDesk" class="headerlink" title="Installing and Configuring RustDesk"></a>Installing and Configuring RustDesk</h2><p>Installation reference：</p><div class="tag link"><a class="link-card" title="RustDesk Installation" href="https://github.com/rustdesk/rustdesk/releases"><div class="left"><img src="https://github.githubassets.com/favicons/favicon.png"/></div><div class="right"><p class="text">RustDesk Installation</p><p class="url">https://github.com/rustdesk/rustdesk/releases</p></div></a></div><p>After installation, open the network settings and enter the IP address of the ID&#x2F;relay server, which is the server running Docker. The controlled machine does not need to enter the relay server, but it’s recommended for the controlling machine to do so. Then, the controlling machine should enter the key (the contents of the .pub file in the data folder above).</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250314214834213.png" alt="windows rustdesk network configuration" loading="lazy"></p><p>Finally, enter the controlled machine’s ID and password to connect.</p><!-- flag of hidden posts -->]]></content>
    
    
    <summary type="html">Using RustDesk with a self-hosted server</summary>
    
    
    
    <category term="tools" scheme="https://even629.com/en/categories/tools/"/>
    
    
    <category term="tools" scheme="https://even629.com/en/tags/tools/"/>
    
  </entry>
  
  <entry>
    <title>CSAPP Data Lab</title>
    <link href="https://even629.com/en/posts/42856/"/>
    <id>https://even629.com/en/posts/42856/</id>
    <published>2025-03-07T12:12:13.000Z</published>
    <updated>2025-03-11T14:31:13.000Z</updated>
    
    <content type="html"><![CDATA[<div class="timeline blue"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>Timeline</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2025-03-07</p></div></div><div class='timeline-item-content'><p>I got as far as the “howManyBits” problem.</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2025-03-07</p></div></div><div class='timeline-item-content'><p>I finished it. Once again, I feel this experiment is quite good.</p></div></div></div><hr><p>Recently, as a teaching assistant for the computer system course, I need to check students’ completion of this CSAPP experiment. I did this experiment during my undergraduate studies, but I’ve basically forgotten everything after so long. So, I’m doing it again and recording the process here.</p><h1 id="Experiment-Environment-Setup"><a href="#Experiment-Environment-Setup" class="headerlink" title="Experiment Environment Setup"></a>Experiment Environment Setup</h1><p>I completed this in the Windows 10 WSL2 environment:</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250304165220672.png" alt="实验环境" loading="lazy"></p><p>For detailed instructions on setting up the environment, please refer to the following link. There is a script for one-click environment setup, which is very convenient:</p><div class="tag link"><a class="link-card" title="CSAPP Environment Setup" href="https://zhuanlan.zhihu.com/p/505497911"><div class="left"><img src="https://static.zhihu.com/heifetz/favicon.ico"/></div><div class="right"><p class="text">CSAPP Environment Setup</p><p class="url">https://zhuanlan.zhihu.com/p/505497911</p></div></a></div><h1 id="Introduction"><a href="#Introduction" class="headerlink" title="Introduction"></a>Introduction</h1><p>Complete the function implementations in bits.c, but there are certain restrictions on the code.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Check whether the code complies with the required specifications</span></span><br><span class="line">./dlc bits.c</span><br><span class="line"><span class="comment"># View score</span></span><br><span class="line">make clean </span><br><span class="line">make </span><br><span class="line">./btest</span><br></pre></td></tr></table></figure><h1 id="Experiment-Content"><a href="#Experiment-Content" class="headerlink" title="Experiment Content"></a>Experiment Content</h1><h2 id="bitXor"><a href="#bitXor" class="headerlink" title="bitXor"></a>bitXor</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * bitXor - x^y using only ~ and &amp; </span></span><br><span class="line"><span class="comment"> *   Example: bitXor(4, 5) = 1</span></span><br><span class="line"><span class="comment"> *   Legal ops: ~ &amp;</span></span><br><span class="line"><span class="comment"> *   Max ops: 14</span></span><br><span class="line"><span class="comment"> *   Rating: 1</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">bitXor</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> &#123; </span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>The requirement is to implement XOR using only ~(Bitwise NOT) and &amp;(Bitwise AND). You may use equivalence calculus from discrete mathematics. XOR means ‘0 if the bits are the same, 1 if different’:</p><p>$$<br>x \oplus y &#x3D; \lnot (\lnot x \land \lnot y) \land \lnot ( x \land y)<br>$$</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">bitXor</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> &#123; </span><br><span class="line">  <span class="keyword">return</span> ( ~(~x &amp; ~y)) &amp; (~(x &amp; y));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="tmin"><a href="#tmin" class="headerlink" title="tmin"></a>tmin</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * tmin - return minimum two&#x27;s complement integer </span></span><br><span class="line"><span class="comment"> *   Legal ops: ! ~ &amp; ^ | + &lt;&lt; &gt;&gt;</span></span><br><span class="line"><span class="comment"> *   Max ops: 4</span></span><br><span class="line"><span class="comment"> *   Rating: 1</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">tmin</span><span class="params">(<span class="type">void</span>)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Returns the smallest two’s complement integer. The definitions of sign-magnitude, one’s complement, and two’s complement are as follows:</p><table><thead><tr><th>Representation</th><th>Definition</th></tr></thead><tbody><tr><td>Sign-magnitude</td><td>The most significant bit is the sign bit (0 indicates positive, 1 indicates negative), and the remaining bits represent the absolute value.</td></tr><tr><td>One’s complement</td><td>For positive numbers, the one’s complement is the same as the sign-magnitude; for negative numbers, the sign bit remains unchanged, and the other bits are bitwise inverted.</td></tr><tr><td>Two’s complement</td><td>For positive numbers, the two’s complement is the same as the sign-magnitude; for negative numbers, the two’s complement is the one’s complement plus 1.</td></tr></tbody></table><p>Two’s complement encoding is asymmetric. Except for the smallest negative number, every negative number corresponds to a positive number. On a 64-bit system, the range of integers represented in two’s complement is:</p><ul><li>Smallest negative number: 0x8000000000000000 (i.e., -2^63).</li><li>Maximum positive number: 0x7FFFFFFFFFFFFFFF (i.e., 2^63 - 1)</li></ul><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">tmin</span><span class="params">(<span class="type">void</span>)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">1</span> &lt;&lt; <span class="number">31</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="isTmax"><a href="#isTmax" class="headerlink" title="isTmax"></a>isTmax</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * isTmax - returns 1 if x is the maximum, two&#x27;s complement number,</span></span><br><span class="line"><span class="comment"> *     and 0 otherwise </span></span><br><span class="line"><span class="comment"> *   Legal ops: ! ~ &amp; ^ | +</span></span><br><span class="line"><span class="comment"> *   Max ops: 10</span></span><br><span class="line"><span class="comment"> *   Rating: 1</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">isTmax</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>Returns 1 if x is the maximum two’s complement value; otherwise, returns 0.</li><li>The maximum value is 0x7FFFFFFF, characterized by the most significant bit being 0 and all others being 1, so 0x7FFFFFFFbecomes 0x8 after adding +0x1. 00000000, with the most significant bit being 1 and all others 0, which is exactly the opposite.</li><li>Here, we need to use the property of XOR, such as x^target. After inverting x and XORing it with target, since XOR outputs 1 for differing bits and 0 for identical bits, only when x and target are exactly the same will x^target be 0x0. Then, by applying the ! operator, we get !(x^target), which is 1 when x equals target and 0 otherwise.<br>For 0x7FFFFFFF, after adding 1, it becomes 0x80000000, due to the opposite characteristic, after bitwise NOT, it becomes 0x7FFFFFFF, so we can use XOR to check if they are the same, that is: !(~(x+1) ^ x).</li><li>Keep thinking: is it only 0x7FFFFFFFthat satisfies this property, where adding 1 is equivalent to bitwise NOT? Obviously, 0xFFFFFFFFalso satisfies this property, because when overflow occurs, the most significant bit is discarded, resulting in 0x0. Therefore, we need to construct an expression combined with !(<del>(x+1) ^ x), called expression1, i.e., !(</del>(x+1) ^ x) &amp; expression1. When x is 0x7,FFFFFFFexpression1 equals 1, and when x is 0xFFFFFFFFit equals 0.</li><li>The exclusion method must use 0x7. FFFFFFFThere is 0xFFFFFFFFThe characteristic of lacking 0, that is, the difference between these two numbers, and the simplest difference is 0x7. FFFFFFFbecomes 0x8 after adding +0x1. FFFFFFFIt is a non-zero number, and 0xFFFFFFFFbecomes 0 after adding 0x1. Therefore, !(x+1) is 0 when x is 0x7. FFFFFFFand is 1 when x is 0xFFFFFFFF!(x+1) is exactly the opposite of what is needed, so adding a NOT operation suffices, that is:</li></ul><p class='p center logo small'>!( ~(x + 1) ^ x) & !!(x + 1)</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">isTmax</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> !( ~(x + <span class="number">1</span>) ^ x) &amp; !!(x + <span class="number">1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="allOddBits"><a href="#allOddBits" class="headerlink" title="allOddBits"></a>allOddBits</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * allOddBits - return 1 if all odd-numbered bits in word set to 1</span></span><br><span class="line"><span class="comment"> *   where bits are numbered from 0 (least significant) to 31 (most significant)</span></span><br><span class="line"><span class="comment"> *   Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1</span></span><br><span class="line"><span class="comment"> *   Legal ops: ! ~ &amp; ^ | + &lt;&lt; &gt;&gt;</span></span><br><span class="line"><span class="comment"> *   Max ops: 12</span></span><br><span class="line"><span class="comment"> *   Rating: 2</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">allOddBits</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>Returns 1 if all odd-numbered bit positions are 1; otherwise, returns 0. That is, if the 1st, 3rd, 5th, 7th, and so on bits of a number are 1 (regardless of other bits), it returns 1; otherwise, it returns 0.</li><li>We can eliminate the influence of all even-numbered bits and focus on the odd bits, for example, by performing x &amp; 0xAAAAAAAAUsing bitwise AND, all even bits become 0; then check whether it equals 0xAAAAAAAAthe same (as explained in isTmax, using bitwise AND to determine if two numbers are identical). Alternatively, you can let x and 0x55555555bitwise OR, so all even bits become 1; then check whether it equals 0xFFFFFFFFthe same. That is:</li></ul><p class='p center logo small'>!((x|0x55555555)^0xFFFFFFFF)</p><p class='p center logo small'>!((x&0xAAAAAAAA)^(0xAAAAAAAA))</p><ul><li>However, due to the experiment’s constraints, you cannot directly write 0xAAAAAAAAlike this; you can only write 0xAA and obtain 0x through bitwise operationsAAAAAAAA</li></ul><div class="tip warning faa-horizontal animated"><p>Note: According to the C standard, shift operations have lower precedence than addition and subtraction.</p></div><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250307163658185.png" alt="https:&#x2F;&#x2F;en.cppreference.com&#x2F;w&#x2F;c&#x2F;language&#x2F;operator_precedence" loading="lazy"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">allOddBits</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">  <span class="comment">// return !((x|0x55555555)^0xFFFFFFFF);</span></span><br><span class="line">  <span class="comment">// return !((x&amp;0xAAAAAAAA)^(0xAAAAAAAA));</span></span><br><span class="line">  <span class="type">int</span> a = <span class="number">0xAA</span>&lt;&lt;<span class="number">8</span>;<span class="comment">//0x00AA</span></span><br><span class="line">  <span class="type">int</span> b = a | <span class="number">0xAA</span>;<span class="comment">//0xAAAA</span></span><br><span class="line">  <span class="type">int</span> c = b&lt;&lt;<span class="number">16</span> | b;<span class="comment">//0xAAAAAAAA</span></span><br><span class="line">  <span class="keyword">return</span> !((x&amp;c)^c);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="negate"><a href="#negate" class="headerlink" title="negate"></a>negate</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * negate - return -x </span></span><br><span class="line"><span class="comment"> *   Example: negate(1) = -1.</span></span><br><span class="line"><span class="comment"> *   Legal ops: ! ~ &amp; ^ | + &lt;&lt; &gt;&gt;</span></span><br><span class="line"><span class="comment"> *   Max ops: 5</span></span><br><span class="line"><span class="comment"> *   Rating: 2</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">negate</span><span class="params">(<span class="type">int</span> x)</span> &#123; </span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>Return the negative of x.</li><li>We know:</li></ul><p class='p center logo small'>x + (-x) = 0</p><p class='p center logo small'>x + (~x) = -1</p><ul><li>Subtracting the two expressions yields:</li></ul><p class='p center logo small'>-x = ~x + 1</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">negate</span><span class="params">(<span class="type">int</span> x)</span> &#123; </span><br><span class="line">  <span class="keyword">return</span> ~x+<span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="isAsciiDigit"><a href="#isAsciiDigit" class="headerlink" title="isAsciiDigit"></a>isAsciiDigit</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * isAsciiDigit - return 1 if 0x30 &lt;= x &lt;= 0x39 (ASCII codes for characters &#x27;0&#x27; to &#x27;9&#x27;)</span></span><br><span class="line"><span class="comment"> *   Example: isAsciiDigit(0x35) = 1.</span></span><br><span class="line"><span class="comment"> *            isAsciiDigit(0x3a) = 0.</span></span><br><span class="line"><span class="comment"> *            isAsciiDigit(0x05) = 0.</span></span><br><span class="line"><span class="comment"> *   Legal ops: ! ~ &amp; ^ | + &lt;&lt; &gt;&gt;</span></span><br><span class="line"><span class="comment"> *   Max ops: 15</span></span><br><span class="line"><span class="comment"> *   Rating: 3</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">isAsciiDigit</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>To check whether x is an ASCII digit, simply determine if x is between 0x30 and 0x39.</li><li>In assembly, comparisons are performed by subtraction which sets the flags. Therefore, we can subtract x from 0x30 and 0x39 respectively and check the sign bit to verify: 0x30 - x should be less than or equal to 0 with the sign bit set to 1, and 0x39 - x should be greater than or equal to 0 with the sign bit 0. However, if x is at the boundary, for example x &#x3D;&#x3D; 0x30, then 0x30 - x equals 0 with the sign bit 0, which also satisfies the condition. Hence, we can replace &lt;&#x3D; with &lt;:</li></ul><p class='p center logo small'>0x30 <= x <= 0x39</p><p>This is equivalent to:</p><p class='p center logo small'>0x2F < x <= 0x39</p><p>Now, does the right side x &lt; 0x39 require an equivalent transformation? Since 0x39 - x should be greater than or equal to 0 with the sign bit 0, and if 0x39 - x &lt; 0 the sign bit is 1, analyzing the boundary conditions shows it is inclusive, so no equivalent transformation is needed (transforming it would exclude the boundary condition).<br>To ensure the sign bit of 0x2F - x is 1 and the sign bit of 0x39 - x is 0, both conditions must be met simultaneously. First, consider 0x2F &lt; x. After subtraction, how can we extract the sign bit? We can perform an arithmetic right shift by 31 bits so that the sign bit fills all 32 bits. That is, if 0x2F - x &lt; 0, then (0x2F + (<del>x + 1)) &gt;&gt; 31 equals 0xFFFFFFFF, and if 0x2F - x &gt;&#x3D; 0, (0x2F + (</del>x + 1)) &gt;&gt; 31 equals 0;</p><p class='p center logo small'>(0x2F + (~x + 1)) >> 31</p><p>Next, consider x &lt;&#x3D; 0x39. Using the same method, if 0x39 - x &lt; 0, then (0x39 + (<del>x + 1)) &gt;&gt; 31 equals 0xFFFFFFFF, and if 0x39 - x &gt;&#x3D; 0, (0x39 + (</del>x + 1)) &gt;&gt; 31 equals 0. We take the negation to satisfy this condition:</p><p class='p center logo small'>~((0x39 + (~x + 1)) >> 31)</p><p>Both conditions must be satisfied simultaneously, so:</p><p class='p center logo small'>(0x2F + (~x + 1)) >> 31 & ~((0x39 + (~x + 1)) >> 31)</p><p>Since the final result is either 1 or 0, we extract the least significant bit:</p><p class='p center logo small'>(0x2F + (~x + 1)) >> 31 & ~((0x39 + (~x + 1)) >> 31) & 0x1</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">isAsciiDigit</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">  <span class="type">int</span> low = (<span class="number">0x2F</span> + (~x + <span class="number">1</span>)) &gt;&gt; <span class="number">31</span>;  <span class="comment">// 0x2F - x &lt; 0 =&gt; x &gt; 0x2F (即 x &gt;= 0x30)</span></span><br><span class="line">  <span class="type">int</span> high = ~((<span class="number">0x39</span> + (~x + <span class="number">1</span>)) &gt;&gt; <span class="number">31</span>);  <span class="comment">// 0x39 - x &gt;= 0 =&gt; x &lt;= 0x39</span></span><br><span class="line">  <span class="keyword">return</span> low &amp; high &amp; <span class="number">0x1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="conditional"><a href="#conditional" class="headerlink" title="conditional"></a>conditional</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * conditional - same as x ? y : z </span></span><br><span class="line"><span class="comment"> *   Example: conditional(2,4,5) = 4</span></span><br><span class="line"><span class="comment"> *   Legal ops: ! ~ &amp; ^ | + &lt;&lt; &gt;&gt;</span></span><br><span class="line"><span class="comment"> *   Max ops: 16</span></span><br><span class="line"><span class="comment"> *   Rating: 3</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">conditional</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y, <span class="type">int</span> z)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>The expression for conditional is the same as x ? y : z.</li><li>To implement returning y or z based on the value of x using only bit operations is very difficult. Although it is easy to determine whether x is zero, it is hard to simultaneously associate x with both y and z. Therefore, we rely on addition operations and assume the return expression is:</li></ul><p class='p center logo small'>a + y + z</p><p>When x !&#x3D; 0, let a &#x3D; -z &#x3D; ~z + 1; When x &#x3D;&#x3D; 0, let a &#x3D; -y &#x3D; ~y + 1 to satisfy the requirement. However, this is also difficult because a depends on both y and z, and a is determined by whether x is zero. Thus, we consider splitting a:</p><p class='p center logo small'>b + c + y + z</p><p>When x is non-zero, let b &#x3D; 0 and c &#x3D; -z &#x3D; ~z + 1; when x is zero, let b &#x3D; -y &#x3D; ~y + 1 and c &#x3D; 0. This way, b depends only on y, and c depends only on z.<br>First, we need to determine whether x is zero. This is straightforward using the NOT operation: when x is non-zero, it yields 0; when x is zero, it yields 1. Let’s focus on b. When !x &#x3D;&#x3D; 0, b should be 0; when !x !&#x3D; 0, b should be ~z + 1. Clearly, the AND operation can achieve this:</p><p class='p center logo small'>b = !x & (~y + 1)</p><p>However, when !x !&#x3D; 0, !x equals 1, and its bitwise AND with ~z + 1 only preserves the least significant bit, which is not necessarily ~z + 1. Therefore, we need to ensure that when x !&#x3D; 0, the result is 0x. FFFFFFFF, and 0 when x &#x3D;&#x3D; 0. Thus, we define a as:</p><p class='p center logo small'>a = ~(!x) + 1</p><p>When x is zero, !x equals 1, and <del>(!x) equals 0x. FFFFFFFE,a&#x3D;&#x3D;0xFFFFFFFF；当x为非零时，!x&#x3D;&#x3D;0，</del>(!x)&#x3D;&#x3D;0xFFFFFFFFSince a &#x3D;&#x3D; 0, the expression for b should be</p><p class='p center logo small'>b = a & (~y + 1)</p><p>Next, consider c. The case for c is exactly the opposite of b, so simply add a ~ to a:</p><p class='p center logo small'>c = ~a & (~z + 1)</p><p>There is no need to worry about addition overflow here.</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">conditional</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y, <span class="type">int</span> z)</span> &#123;</span><br><span class="line">  <span class="type">int</span> a = ~(!x)+<span class="number">1</span>;</span><br><span class="line">  <span class="type">int</span> b = a&amp;(~y+<span class="number">1</span>);</span><br><span class="line">  <span class="type">int</span> c = ~a&amp;(~z+<span class="number">1</span>);</span><br><span class="line">  <span class="keyword">return</span> b+y+c+z;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="isLessOrEqual"><a href="#isLessOrEqual" class="headerlink" title="isLessOrEqual"></a>isLessOrEqual</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * isLessOrEqual - if x &lt;= y  then return 1, else return 0 </span></span><br><span class="line"><span class="comment"> *   Example: isLessOrEqual(4,5) = 1.</span></span><br><span class="line"><span class="comment"> *   Legal ops: ! ~ &amp; ^ | + &lt;&lt; &gt;&gt;</span></span><br><span class="line"><span class="comment"> *   Max ops: 24</span></span><br><span class="line"><span class="comment"> *   Rating: 3</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">isLessOrEqual</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>Return 1 if x &lt;&#x3D; y; otherwise, return 0.</li><li>To compare values using subtraction, compute y - x. If y - x &gt;&#x3D; 0 (sign bit is 0), return 1; if y - x &lt; 0 (sign bit is 1), return 0. Since y - x &#x3D; y + ~x + 1, right shift by 31 bits to extract the sign bit. We apply bitwise negation to ensure that when the sign bit is 0, the result is 1; when the sign bit is 1, the result is 0:</li></ul><p class='p center logo small'>~((y + (~x + 1)) >> 31) & 0x1</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">isLessOrEqual</span><span class="params">(<span class="type">int</span> x, <span class="type">int</span> y)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> ~((y+(~x+<span class="number">1</span>))&gt;&gt;<span class="number">31</span>) &amp;<span class="number">0x1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="logicalNeg"><a href="#logicalNeg" class="headerlink" title="logicalNeg"></a>logicalNeg</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * logicalNeg - implement the ! operator, using all of </span></span><br><span class="line"><span class="comment"> *              the legal operators except !</span></span><br><span class="line"><span class="comment"> *   Examples: logicalNeg(3) = 0, logicalNeg(0) = 1</span></span><br><span class="line"><span class="comment"> *   Legal ops: ~ &amp; ^ | + &lt;&lt; &gt;&gt;</span></span><br><span class="line"><span class="comment"> *   Max ops: 12</span></span><br><span class="line"><span class="comment"> *   Rating: 4 </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">logicalNeg</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>Implement the NOT operation: for !x, return 1 when x is 0, and return 0 when x is non-zero.</li><li>The most intuitive difference between 0 and non-zero values is that every bit of 0 is zero, while a non-zero value has at least one bit set to 1. However, since we cannot use looped shift operations to determine this, we must find an alternative approach.</li><li>Another distinguishing characteristic between 0 and non-zero values is that the negative of 0 is still 0, i.e., ~0 + 1 &#x3D; 0, whereas the negative of a non-zero number is not 0. We can leverage this fact to check whether the negative of x equals x itself. Previously, we used a trick with XOR to check if two numbers are equal: this expression returns 0 when x is 0, and non-zero when x is non-zero, but this effectively does nothing.</li></ul><p class='p center logo small'>(~x+1)^x</p><p>We can use another insight: the sign bit of a non-zero number and its negative must be opposite—one is 1, the other 0—while the sign bit of 0 and its negative are both 0. Therefore, by OR-ing the two, we get an expression whose sign bit is 1 when non-zero, and 0 when zero.</p><p class='p center logo small'>(~x+1)|x</p><p>Next, we extract the sign bit and invert it, because we want to return 1 when the input is 0, and 0 otherwise. We used this technique in the previous problem: perform an arithmetic right shift by 31 bits, invert the result, and then AND with 0x1 to isolate the least significant bit:</p><p class='p center logo small'>~(((~x+1)|x)>>31) & 0x1</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">logicalNeg</span><span class="params">(<span class="type">int</span> x)</span> &#123; </span><br><span class="line">   <span class="keyword">return</span> ~(((~x+<span class="number">1</span>)|x)&gt;&gt;<span class="number">31</span>) &amp; <span class="number">0x1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="howManyBits"><a href="#howManyBits" class="headerlink" title="howManyBits"></a>howManyBits</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* howManyBits - return the minimum number of bits required to represent x in</span></span><br><span class="line"><span class="comment"> *             two&#x27;s complement</span></span><br><span class="line"><span class="comment"> *  Examples: howManyBits(12) = 5</span></span><br><span class="line"><span class="comment"> *            howManyBits(298) = 10</span></span><br><span class="line"><span class="comment"> *            howManyBits(-5) = 4</span></span><br><span class="line"><span class="comment"> *            howManyBits(0)  = 1</span></span><br><span class="line"><span class="comment"> *            howManyBits(-1) = 1</span></span><br><span class="line"><span class="comment"> *            howManyBits(0x80000000) = 32</span></span><br><span class="line"><span class="comment"> *  Legal ops: ! ~ &amp; ^ | + &lt;&lt; &gt;&gt;</span></span><br><span class="line"><span class="comment"> *  Max ops: 90</span></span><br><span class="line"><span class="comment"> *  Rating: 4</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">howManyBits</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>Return the number of bits required to represent x in binary two’s complement form. Essentially, this involves finding the position of the most significant 1 bit and then adding 1 bit for the sign bit. This problem is somewhat challenging and not very intuitive. Below is an implementation method from someone else.</li><li>Here, we use a binary search approach:<br>First, consider positive numbers and zero.</li></ul><ol><li>High 16 bits: Check if there is a 1 in the high 16 bits; if so, at least 16 bits are needed.</li><li>High 8 bits: Within the remaining 16 bits, check if there is a 1 in the high 8 bits.</li><li>High 4 bits: Within the remaining 8 bits, check if there is a 1 in the high 4 bits.</li><li>High 2 bits: Within the remaining 4 bits, check if there is a 1 in the high 2 bits.</li><li>High bit: Among the remaining 2 bits, check if the higher bit is 1.</li><li>Least significant bit: The last remaining bit.<br>Finally, sum the bit counts of all parts and add 1 for the sign bit.</li></ol><ul><li>Handling negative numbers:<br>The flag is x &gt;&gt; 31, which is the sign bit. If x is negative, flag is 1; otherwise, it is 0.</li></ul><ol><li>If x is negative (flag &#x3D;&#x3D; 1), then x is bitwise inverted: x &#x3D; ~x.</li><li>If x is non-negative (flag &#x3D;&#x3D; 0), x remains unchanged.<br>In two’s complement representation of negative numbers, the sign bit and the value bits are combined. If you directly calculate the number of significant bits for a negative number, the sign bit will cause incorrect results. For example:<br>The two’s complement of -1 is 11111111 11111111 11111111 11111111, if we directly count the bits, we get 32 bits, but in reality, we only care about the number of effective bits.<br>By applying bitwise negation, the two’s complement representation of a negative number is converted into a positive number, and the number of effective bits in its binary form remains the same as that of the original negative number. For example:</li></ol><ul><li>The two’s complement of -1 is 11111111 11111111 11111111 11111111, and after negation it becomes 00000000 00000000 00000000 00000000, with an effective bit count of 1.</li><li>The two’s complement of -2 is 11111111 11111111 11111111 11111110, and after negation it becomes 00000000 00000000 00000000 00000001, with an effective bit count of 2.</li></ul><div class="tag link"><a class="link-card" title="howManyBits" href="https://zhuanlan.zhihu.com/p/559005736"><div class="left"><img src="https://static.zhihu.com/heifetz/favicon.ico"/></div><div class="right"><p class="text">howManyBits</p><p class="url">https://zhuanlan.zhihu.com/p/559005736</p></div></a></div><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">howManyBits</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">  <span class="type">int</span> b16, b8, b4, b2, b1, b0;</span><br><span class="line">  <span class="type">int</span> flag = x &gt;&gt; <span class="number">31</span>;</span><br><span class="line">  x = (flag &amp; ~x) | (~flag &amp; x);  <span class="comment">// If the sign bit of x is 0, it remains unchanged; if the sign bit of x is 1, invert all bits</span></span><br><span class="line">  </span><br><span class="line">  b16 = !!(x &gt;&gt; <span class="number">16</span>) &lt;&lt; <span class="number">4</span>;  <span class="comment">// Check if the number is greater than or equal to 2^16</span></span><br><span class="line">  x &gt;&gt;= b16;  </span><br><span class="line">  b8 = !!(x &gt;&gt; <span class="number">8</span>) &lt;&lt; <span class="number">3</span>;    <span class="comment">// Check if the number is greater than or equal to 2^8</span></span><br><span class="line">  x &gt;&gt;= b8;</span><br><span class="line">  b4 = !!(x &gt;&gt; <span class="number">4</span>) &lt;&lt; <span class="number">2</span>;    <span class="comment">// Check if the number is greater than or equal to 2^4</span></span><br><span class="line">  x &gt;&gt;= b4;</span><br><span class="line">  b2 = !!(x &gt;&gt; <span class="number">2</span>) &lt;&lt; <span class="number">1</span>;    <span class="comment">// Check if the number is greater than or equal to 2^2</span></span><br><span class="line">  x &gt;&gt;= b2;</span><br><span class="line">  b1 = !!(x &gt;&gt; <span class="number">1</span>);         <span class="comment">// Check if the number is greater than or equal to 2^1</span></span><br><span class="line">  x &gt;&gt;= b1;</span><br><span class="line">  b0 = x;                  <span class="comment">// Check if the number is greater than or equal to 2^0</span></span><br><span class="line">  </span><br><span class="line">  <span class="keyword">return</span> b0 + b1 + b2 + b4 + b8 + b16 + <span class="number">1</span>;  <span class="comment">// Return the total number of bits required</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="floatScale2"><a href="#floatScale2" class="headerlink" title="floatScale2"></a>floatScale2</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * floatScale2 - Return bit-level equivalent of expression 2*f for</span></span><br><span class="line"><span class="comment"> *   floating point argument f.</span></span><br><span class="line"><span class="comment"> *   Both the argument and result are passed as unsigned int&#x27;s, but</span></span><br><span class="line"><span class="comment"> *   they are to be interpreted as the bit-level representation of</span></span><br><span class="line"><span class="comment"> *   single-precision floating point values.</span></span><br><span class="line"><span class="comment"> *   When argument is NaN, return argument</span></span><br><span class="line"><span class="comment"> *   Legal ops: Any integer/unsigned operations incl. ||, &amp;&amp;. also if, while</span></span><br><span class="line"><span class="comment"> *   Max ops: 30</span></span><br><span class="line"><span class="comment"> *   Rating: 4</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">unsigned</span> <span class="title function_">floatScale2</span><span class="params">(<span class="type">unsigned</span> uf)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li><p>Multiply a single-precision floating-point number (float) by 2, and return the binary representation of the result. The function’s input and output are both of type unsigned int, but they actually represent the binary bit pattern of a single-precision floating-point number. When the input is NaN, return it unchanged. Also, finally I get to use if and while😭😭😭</p></li><li><p>Let’s first review the concepts of <strong>IEEE 754</strong> floating-point numbers:</p></li></ul><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/Snipaste_2025-03-11_15-53-54.png" alt="Representation of IEEE 754" loading="lazy"></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/Snipaste_2025-03-11_15-54-47.png" alt="Single-precision float and double-precision double" loading="lazy"></p><p>There are three categories of floating-point numbers defined by IEEE 754:<br><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/Snipaste_2025-03-11_15-55-12.png" alt="Category 1: Normalized number" loading="lazy"></p><p>Denormalized numbers represent very small values close to zero, preventing floating-point underflow and ensuring the continuity of floating-point computations.<br><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/Snipaste_2025-03-11_15-55-34.png" alt="类别2：非规格化数" loading="lazy"></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/Snipaste_2025-03-11_15-55-43.png" alt="类别3：特殊值" loading="lazy"></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/Snipaste_2025-03-11_16-38-57.png" alt="IEEE 754 Representation Range" loading="lazy"></p><p>First, we extract the sign bit (sign), the fraction (frac), and the exponent (exp):</p><p class='p center logo small'>sign=uf>>31&0x1</p><p class='p center logo small'>frac=uf&0x7FFFFF</p><p class='p center logo small'>exp = (uf&0x7f800000)>>23</p><p>Based on the exponent, determine whether this floating-point number is normalized, denormalized, or one of the special cases.</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">unsigned</span> <span class="title function_">floatScale2</span><span class="params">(<span class="type">unsigned</span> uf)</span> &#123; </span><br><span class="line">  <span class="type">unsigned</span> <span class="built_in">exp</span> = (uf &amp; <span class="number">0x7f800000</span>) &gt;&gt; <span class="number">23</span>;</span><br><span class="line">  <span class="type">unsigned</span> sign = uf &gt;&gt; <span class="number">31</span> &amp; <span class="number">0x1</span>;</span><br><span class="line">  <span class="type">unsigned</span> frac = uf &amp; <span class="number">0x7FFFFF</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">if</span> (<span class="built_in">exp</span> == <span class="number">0</span>) &#123;  <span class="comment">// Denormalized number, exponent is 0, just multiply frac by 2</span></span><br><span class="line">    frac &lt;&lt;= <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">return</span> (sign &lt;&lt; <span class="number">31</span>) | (<span class="built_in">exp</span> &lt;&lt; <span class="number">23</span>) | frac;</span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">exp</span> == <span class="number">0xFF</span>) &#123;  <span class="comment">// Special case, NaN</span></span><br><span class="line">    <span class="keyword">return</span> uf;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="built_in">exp</span>++;  <span class="comment">// Multiply by 2, equivalent to E + 1</span></span><br><span class="line">    <span class="keyword">return</span> (sign &lt;&lt; <span class="number">31</span>) | (<span class="built_in">exp</span> &lt;&lt; <span class="number">23</span>) | frac;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="floatFloat2Int"><a href="#floatFloat2Int" class="headerlink" title="floatFloat2Int"></a>floatFloat2Int</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * floatFloat2Int - Return bit-level equivalent of expression (int) f</span></span><br><span class="line"><span class="comment"> *   for floating point argument f.</span></span><br><span class="line"><span class="comment"> *   Argument is passed as unsigned int, but</span></span><br><span class="line"><span class="comment"> *   it is to be interpreted as the bit-level representation of a</span></span><br><span class="line"><span class="comment"> *   single-precision floating point value.</span></span><br><span class="line"><span class="comment"> *   Anything out of range (including NaN and infinity) should return</span></span><br><span class="line"><span class="comment"> *   0x80000000u.</span></span><br><span class="line"><span class="comment"> *   Legal ops: Any integer/unsigned operations incl. ||, &amp;&amp;. also if, while</span></span><br><span class="line"><span class="comment"> *   Max ops: 30</span></span><br><span class="line"><span class="comment"> *   Rating: 4</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">floatFloat2Int</span><span class="params">(<span class="type">unsigned</span> uf)</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>Represent the input IEEE 754 floating-point number as an int; if it exceeds the representable range, return 0x8. 0000000u。</li><li>If it is a denormalized number, return 0 immediately; if it is a special case, return 0x8 immediately. 0000000u</li><li>If it is a normalized number, we first need to check whether it exceeds the int representation range. An int consists of 32 bits in total, with one bit for the sign bit. The maximum value is 2^31, and the minimum value is -(2^31 + 1). Therefore, the exponent E cannot exceed 30 (when E is 31, left shifting by E bits will overwrite the sign bit). When the exponent E is less than 0, it means the number is less than 1, so we directly return 0. Also:</li><li>sign <strong>1 bit</strong></li><li>exp <strong>8 bits</strong></li><li>frac <strong>23 bits</strong></li></ul><p>$$<br>V &#x3D; (-1)^{sign} \times 2^{exp - 127} \times (1 + frac)<br>$$</p><p>We can consider it as <strong>1frac</strong> (the 24th bit is 1, and bits 1 to 23 form frac), which is equivalent to <strong>1.frac</strong> (integer part 1, fractional part frac) left shifted by 23 bits. At this point, the exponent is E, meaning it should be multiplied by 2 to the power of E, i.e., left shifted by E bits. Therefore, when E is less than 23, we should right shift by (23 - E) bits to truncate the last (23 - E) bits of frac. When E is greater than 23, since this is equivalent to having already shifted left by 23 bits, you only need to shift left by (E - 23) additional bits.</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">floatFloat2Int</span><span class="params">(<span class="type">unsigned</span> uf)</span> &#123;</span><br><span class="line">  <span class="type">unsigned</span> <span class="built_in">exp</span> = (uf &amp; <span class="number">0x7f800000</span>) &gt;&gt; <span class="number">23</span>;</span><br><span class="line">  <span class="type">unsigned</span> sign = uf &gt;&gt; <span class="number">31</span> &amp; <span class="number">0x1</span>;</span><br><span class="line">  <span class="type">unsigned</span> frac = uf &amp; <span class="number">0x7FFFFF</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">if</span> (<span class="built_in">exp</span> == <span class="number">0xFF</span>) &#123;  <span class="comment">// Special case</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0x80000000u</span>;</span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">exp</span> == <span class="number">0</span>) &#123;  <span class="comment">// Denormalized number</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0x0</span>;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;                   <span class="comment">// Normalized number</span></span><br><span class="line">    <span class="type">int</span> E = <span class="built_in">exp</span> - <span class="number">127</span>;  <span class="comment">// Exponent, note not to set as unsigned</span></span><br><span class="line">    <span class="keyword">if</span> (E &gt;= <span class="number">31</span>) &#123;           <span class="comment">// Out of range</span></span><br><span class="line">      <span class="keyword">return</span> <span class="number">0x80000000u</span>;</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (E &lt; <span class="number">0</span>) &#123;  <span class="comment">// If E &lt; 0, it means the number is smaller than 1, return 0</span></span><br><span class="line">      <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    frac = frac | (<span class="number">1</span> &lt;&lt; <span class="number">23</span>);  <span class="comment">// Set the implicit 1 in the fraction</span></span><br><span class="line">    <span class="keyword">if</span> (E &lt; <span class="number">23</span>) &#123;</span><br><span class="line">      frac = frac &gt;&gt; (<span class="number">23</span> - E);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      frac = frac &lt;&lt; (E - <span class="number">23</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (sign == <span class="number">0</span>) &#123;  <span class="comment">// Return positive or negative based on the sign bit</span></span><br><span class="line">      <span class="keyword">return</span> frac;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">return</span> -frac;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="floatPower2"><a href="#floatPower2" class="headerlink" title="floatPower2"></a>floatPower2</h2><p>Problem:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment"> * floatPower2 - Return bit-level equivalent of the expression 2.0^x</span></span><br><span class="line"><span class="comment"> *   (2.0 raised to the power x) for any 32-bit integer x.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *   The unsigned value that is returned should have the identical bit</span></span><br><span class="line"><span class="comment"> *   representation as the single-precision floating-point number 2.0^x.</span></span><br><span class="line"><span class="comment"> *   If the result is too small to be represented as a denorm, return</span></span><br><span class="line"><span class="comment"> *   0. If too large, return +INF.</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> *   Legal ops: Any integer/unsigned operations incl. ||, &amp;&amp;. Also if, while </span></span><br><span class="line"><span class="comment"> *   Max ops: 30 </span></span><br><span class="line"><span class="comment"> *   Rating: 4</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">unsigned</span> <span class="title function_">floatPower2</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">2</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>Calculate 2.0^x and return its unsigned representation according to IEEE 754. If the result is too small—so small that even denormalized numbers cannot represent it—return 0. If the result is too large, return +INF. Clearly, this problem primarily tests the representable range of IEEE 754.</li></ul><p>For <strong>float single precision</strong></p><ul><li>Sign bit sign: 1 bit</li><li>Exponent exp: 8 bits</li><li>Fraction frac: 23 bits</li></ul><p><strong>Representable range</strong></p><ul><li><p>Normalized numbers: The exponent exp is neither all zeros nor all ones,<br>$<br>V &#x3D; (-1)^S \times 2^E \times M &#x3D; (-1)^{sign} \times 2^{exp - bias} \times (1 + frac)<br>$<br>The exponent ranges from 1 to 254, with E &#x3D; Exp - Bias &#x3D; Exp - 127, so E ranges from -126 to 127. For frac, the minimum value is 0 and the maximum is 1 - 2^{-23}. Therefore, ignoring S,<br>$<br>V_{max} &#x3D;  (-1)^S \times 2^{127} \times (2 - 2^{-23}) &#x3D; (-1)^S \times 2^{127} \times (2 - 2^{-23})<br>$<br>$<br>V_{min} &#x3D; (-1)^S \times 2^{-126} \times (1 + 0) &#x3D; (-1)^S \times 2^{-126}<br>$</p></li><li><p>Denormalized number: exponent all zeros<br>$<br>V &#x3D; (-1)^S \times 2^E \times M &#x3D; (-1)^{sign} \times 2^{1 - Bias} \times (0 + frac)<br>$<br>The exponent exp is all zeros, so E &#x3D; 1 - Bias &#x3D; 1 - 127 &#x3D; -126. Therefore:<br>$<br>V &#x3D; (-1)^{sign} \times 2^{-126} \times (0 + frac)<br>$<br>For frac, the minimum value is 0, but the smallest representable nonzero value is 2^{-23}. Values between 0 and 2^{-23} cannot be represented. The maximum value is 1 - 2^{-23}. Thus, when frac is 0, the value is 0. However, to calculate the smallest representable nonzero value, frac must be set to 2^{-23}, ignoring S:<br>$<br>V_{max} &#x3D; (-1)^S \times 2^{-126} \times (0 + 1 - 2^{-23}) &#x3D; (-1)^S \times 2^{-126} \times (1 - 2^{-23})<br>$<br>$<br>V_{min} &#x3D; (-1)^S \times 2^{-126} \times (0 + 2^{-23}) &#x3D; (-1)^S \times 2^{-149}<br>$</p></li><li><p>Special values</p></li></ul><ol><li>+infinity: all bits of exp are 1, frac is 0, and S is 0</li><li>-infinity: all bits of exp are 1, frac is 0, and S is 1</li><li>NaN: all bits of exp are 1, and frac is not 0</li></ol><p>Therefore, based on the above analysis:</p><ul><li>Return +NaN when x &gt; 127</li><li>A normalized number when -126 ≤ x ≤ 127</li><li>Denormalized number when -149 ≤ x &lt; -126</li><li>Return 0 when x &lt; -149 because the value is too small to represent</li></ul><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">unsigned</span> <span class="title function_">floatPower2</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">  <span class="keyword">if</span> (x &gt; <span class="number">127</span>) &#123;  <span class="comment">// Return +infinity, S=0, exp=0xFF, frac=0;</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0xFF</span> &lt;&lt; <span class="number">23</span>;</span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="number">-126</span> &lt;= x &amp;&amp; x &lt;= <span class="number">127</span>) &#123;  <span class="comment">// Normalized number, exp = E + Bias = E + 127</span></span><br><span class="line">    <span class="keyword">return</span> (x + <span class="number">127</span>) &lt;&lt; <span class="number">23</span>;</span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="number">-149</span> &lt;= x &amp;&amp; x &lt; <span class="number">-126</span>) &#123;  <span class="comment">// Denormalized number, exp=0, E = 1 - Bias = -126, 2^(-126) * frac</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">1</span> &lt;&lt; (<span class="number">23</span> - (-x - <span class="number">126</span>));  <span class="comment">// E already has 2^(-126), when frac is 0x1, it represents 2^(-23), assuming input x is -127, frac should be 2^(-1), i.e., 1 shifted left by 22 bits</span></span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;  <span class="comment">// x &lt; -149, too small, return 0</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><!-- flag of hidden posts -->]]></content>
    
    
    <summary type="html">Computer system - CSAPP Data Lab</summary>
    
    
    
    <category term="CSAPP" scheme="https://even629.com/en/categories/CSAPP/"/>
    
    
    <category term="CSAPP" scheme="https://even629.com/en/tags/CSAPP/"/>
    
  </entry>
  
  <entry>
    <title>Summary of EDK2 Protocol Retrieval</title>
    <link href="https://even629.com/en/posts/42855/"/>
    <id>https://even629.com/en/posts/42855/</id>
    <published>2025-02-25T06:45:13.000Z</published>
    <updated>2025-02-25T06:45:13.000Z</updated>
    
    <content type="html"><![CDATA[<div class="timeline blue"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>Timeline</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2025-02-25</p></div></div><div class='timeline-item-content'><ol><li>Added OpenProtocol, HandleProtocol, LocateProtocol, OpenProtocolInformation, CloseProtocol</li></ol></div></div></div><hr><p>The interfaces related to Protocol are defined in UefiSpec.h.</p><div class='checkbox cyan checked'><input type="checkbox" checked="checked"/>            <p>EFI_HANDLE_PROTOCOL HandleProtocol;</p>            </div><div class='checkbox cyan'><input type="checkbox" />            <p>EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify;</p>            </div><div class='checkbox cyan'><input type="checkbox" />            <p>EFI_LOCATE_HANDLE LocateHandle;</p>            </div><div class='checkbox cyan'><input type="checkbox" />            <p>EFI_LOCATE_DEVICE_PATH LocateDevicePath;</p>            </div><div class='checkbox cyan checked'><input type="checkbox" checked="checked"/>            <p>EFI_OPEN_PROTOCOL OpenProtocol;</p>            </div><div class='checkbox cyan checked'><input type="checkbox" checked="checked"/>            <p>EFI_CLOSE_PROTOCOL CloseProtocol;</p>            </div><div class='checkbox cyan checked'><input type="checkbox" checked="checked"/>            <p>EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation;</p>            </div><div class='checkbox cyan checked'><input type="checkbox" checked="checked"/>            <p>EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle;</p>            </div><div class='checkbox cyan'><input type="checkbox" />            <p>EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer;</p>            </div><div class='checkbox cyan checked'><input type="checkbox" checked="checked"/>            <p>EFI_LOCATE_PROTOCOL LocateProtocol;</p>            </div><div class='checkbox cyan'><input type="checkbox" />            <p>EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface;</p>            </div><div class='checkbox cyan'><input type="checkbox" />            <p>EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface;</p>            </div><div class='checkbox cyan'><input type="checkbox" />            <p>EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface;</p>            </div><div class='checkbox cyan'><input type="checkbox" />            <p>EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces;</p>            </div><div class='checkbox cyan'><input type="checkbox" />            <p>EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces;</p>            </div><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">///</span></span><br><span class="line"><span class="comment">/// EFI Boot Services Table.</span></span><br><span class="line"><span class="comment">///</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">  <span class="comment">///</span></span><br><span class="line">  <span class="comment">/// The table header for the EFI Boot Services Table.</span></span><br><span class="line">  <span class="comment">///</span></span><br><span class="line">  EFI_TABLE_HEADER                              Hdr;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// Task Priority Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_RAISE_TPL                                 RaiseTPL;</span><br><span class="line">  EFI_RESTORE_TPL                               RestoreTPL;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// Memory Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_ALLOCATE_PAGES                            AllocatePages;</span><br><span class="line">  EFI_FREE_PAGES                                FreePages;</span><br><span class="line">  EFI_GET_MEMORY_MAP                            GetMemoryMap;</span><br><span class="line">  EFI_ALLOCATE_POOL                             AllocatePool;</span><br><span class="line">  EFI_FREE_POOL                                 FreePool;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// Event &amp; Timer Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_CREATE_EVENT                              CreateEvent;</span><br><span class="line">  EFI_SET_TIMER                                 SetTimer;</span><br><span class="line">  EFI_WAIT_FOR_EVENT                            WaitForEvent;</span><br><span class="line">  EFI_SIGNAL_EVENT                              SignalEvent;</span><br><span class="line">  EFI_CLOSE_EVENT                               CloseEvent;</span><br><span class="line">  EFI_CHECK_EVENT                               CheckEvent;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// Protocol Handler Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_INSTALL_PROTOCOL_INTERFACE                InstallProtocolInterface;</span><br><span class="line">  EFI_REINSTALL_PROTOCOL_INTERFACE              ReinstallProtocolInterface;</span><br><span class="line">  EFI_UNINSTALL_PROTOCOL_INTERFACE              UninstallProtocolInterface;</span><br><span class="line">  EFI_HANDLE_PROTOCOL                           HandleProtocol;</span><br><span class="line">  VOID                                          *Reserved;</span><br><span class="line">  EFI_REGISTER_PROTOCOL_NOTIFY                  RegisterProtocolNotify;</span><br><span class="line">  EFI_LOCATE_HANDLE                             LocateHandle;</span><br><span class="line">  EFI_LOCATE_DEVICE_PATH                        LocateDevicePath;</span><br><span class="line">  EFI_INSTALL_CONFIGURATION_TABLE               InstallConfigurationTable;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// Image Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_IMAGE_LOAD                                LoadImage;</span><br><span class="line">  EFI_IMAGE_START                               StartImage;</span><br><span class="line">  EFI_EXIT                                      Exit;</span><br><span class="line">  EFI_IMAGE_UNLOAD                              UnloadImage;</span><br><span class="line">  EFI_EXIT_BOOT_SERVICES                        ExitBootServices;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// Miscellaneous Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_GET_NEXT_MONOTONIC_COUNT                  GetNextMonotonicCount;</span><br><span class="line">  EFI_STALL                                     Stall;</span><br><span class="line">  EFI_SET_WATCHDOG_TIMER                        SetWatchdogTimer;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// DriverSupport Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_CONNECT_CONTROLLER                        ConnectController;</span><br><span class="line">  EFI_DISCONNECT_CONTROLLER                     DisconnectController;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// Open and Close Protocol Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_OPEN_PROTOCOL                             OpenProtocol;</span><br><span class="line">  EFI_CLOSE_PROTOCOL                            CloseProtocol;</span><br><span class="line">  EFI_OPEN_PROTOCOL_INFORMATION                 OpenProtocolInformation;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// Library Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_PROTOCOLS_PER_HANDLE                      ProtocolsPerHandle;</span><br><span class="line">  EFI_LOCATE_HANDLE_BUFFER                      LocateHandleBuffer;</span><br><span class="line">  EFI_LOCATE_PROTOCOL                           LocateProtocol;</span><br><span class="line">  EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES      InstallMultipleProtocolInterfaces;</span><br><span class="line">  EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES    UninstallMultipleProtocolInterfaces;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// 32-bit CRC Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_CALCULATE_CRC32                           CalculateCrc32;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  <span class="comment">// Miscellaneous Services</span></span><br><span class="line">  <span class="comment">//</span></span><br><span class="line">  EFI_COPY_MEM                                  CopyMem;</span><br><span class="line">  EFI_SET_MEM                                   SetMem;</span><br><span class="line">  EFI_CREATE_EVENT_EX                           CreateEventEx;</span><br><span class="line">&#125; EFI_BOOT_SERVICES;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="OpenProtocol"><a href="#OpenProtocol" class="headerlink" title="OpenProtocol"></a>OpenProtocol</h1><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250207181806644.png" loading="lazy"></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250207182821554.png" loading="lazy"></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250225144030827.png" loading="lazy"></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250225144054460.png" loading="lazy"></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250225144113071.png" loading="lazy"></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250225144141665.png" alt="OpenProtocol" loading="lazy"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// MdePkg/Include/Uefi/UefiSpec.h</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL   0x00000001</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> EFI_OPEN_PROTOCOL_GET_PROTOCOL         0x00000002</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> EFI_OPEN_PROTOCOL_TEST_PROTOCOL        0x00000004</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER  0x00000008</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> EFI_OPEN_PROTOCOL_BY_DRIVER            0x00000010</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> EFI_OPEN_PROTOCOL_EXCLUSIVE            0x00000020</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">  Queries a handle to determine if it supports a specified protocol. If the protocol is supported by the</span></span><br><span class="line"><span class="comment">  handle, it opens the protocol on behalf of the calling agent.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @param[in]   Handle           The handle for the protocol interface that is being opened.</span></span><br><span class="line"><span class="comment">  @param[in]   Protocol         The published unique identifier of the protocol.</span></span><br><span class="line"><span class="comment">  @param[out]  Interface        Supplies the address where a pointer to the corresponding Protocol</span></span><br><span class="line"><span class="comment">                                Interface is returned.</span></span><br><span class="line"><span class="comment">  @param[in]   AgentHandle      The handle of the agent that is opening the protocol interface</span></span><br><span class="line"><span class="comment">                                specified by Protocol and Interface.</span></span><br><span class="line"><span class="comment">  @param[in]   ControllerHandle If the agent that is opening a protocol is a driver that follows the</span></span><br><span class="line"><span class="comment">                                UEFI Driver Model, then this parameter is the controller handle</span></span><br><span class="line"><span class="comment">                                that requires the protocol interface. If the agent does not follow</span></span><br><span class="line"><span class="comment">                                the UEFI Driver Model, then this parameter is optional and may</span></span><br><span class="line"><span class="comment">                                be NULL.</span></span><br><span class="line"><span class="comment">  @param[in]   Attributes       The open mode of the protocol </span></span><br><span class="line"><span class="comment">  interface specified by Handle</span></span><br><span class="line"><span class="comment">                                and Protocol.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @retval EFI_SUCCESS           An item was added to the open list for the protocol interface, and the</span></span><br><span class="line"><span class="comment">                                protocol interface was returned in Interface.</span></span><br><span class="line"><span class="comment">  @retval EFI_UNSUPPORTED       Handle does not support Protocol.</span></span><br><span class="line"><span class="comment">  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.</span></span><br><span class="line"><span class="comment">  @retval EFI_ACCESS_DENIED     Required attributes can&#x27;t be supported in current environment.</span></span><br><span class="line"><span class="comment">  @retval EFI_ALREADY_STARTED   Item on the open list already has requierd attributes whose agent</span></span><br><span class="line"><span class="comment">                                handle is the same as AgentHandle.</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">typedef</span></span><br><span class="line"><span class="title function_">EFI_STATUS</span></span><br><span class="line"><span class="params">(EFIAPI *EFI_OPEN_PROTOCOL)</span><span class="params">(</span></span><br><span class="line"><span class="params">  IN  EFI_HANDLE                Handle,</span></span><br><span class="line"><span class="params">  IN  EFI_GUID                  *Protocol,</span></span><br><span class="line"><span class="params">  OUT VOID                      **Interface  OPTIONAL,</span></span><br><span class="line"><span class="params">  IN  EFI_HANDLE                AgentHandle,</span></span><br><span class="line"><span class="params">  IN  EFI_HANDLE                ControllerHandle,</span></span><br><span class="line"><span class="params">  IN  UINT32                    Attributes</span></span><br><span class="line"><span class="params">  )</span>;</span><br></pre></td></tr></table></figure><p>Example:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Guid/FileInfo.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/BaseMemoryLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/CacheMaintenanceLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/MemoryAllocationLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/UefiBootServicesTableLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/UefiLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Protocol/SimpleFileSystem.h&gt;</span>  </span></span><br><span class="line"></span><br><span class="line">EFI_STATUS</span><br><span class="line"><span class="title function_">ReadFileByName</span><span class="params">(IN CHAR16 *FileName, OUT UINT8 **FileData, OUT UINTN *FileSize)</span> &#123;</span><br><span class="line">  EFI_FILE_INFO *FileInfo;</span><br><span class="line">  UINTN FileInfoSize;</span><br><span class="line">  EFI_FILE_PROTOCOL *FileHandle = <span class="literal">NULL</span>;</span><br><span class="line">  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;</span><br><span class="line">  EFI_FILE_PROTOCOL *Root;</span><br><span class="line">  EFI_STATUS Status;</span><br><span class="line">  UINTN HandleCount = <span class="number">0</span>;</span><br><span class="line">  UINTN HandleIndex = <span class="number">0</span>;</span><br><span class="line">  EFI_HANDLE *HandleBuffer = <span class="literal">NULL</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="comment">// Find all handles of SimpleFileSystemProtocol</span></span><br><span class="line">  Status =</span><br><span class="line">      gBS-&gt;LocateHandleBuffer(ByProtocol, &amp;gEfiSimpleFileSystemProtocolGuid,</span><br><span class="line">                              <span class="literal">NULL</span>, &amp;HandleCount, &amp;HandleBuffer);</span><br><span class="line">  <span class="keyword">if</span> (EFI_ERROR(Status) || HandleCount == <span class="number">0</span>) &#123;</span><br><span class="line">    Print(<span class="string">L&quot;Locate SimpleFileSystemProtocolHandle Buffer error&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> Status;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> (HandleIndex = <span class="number">0</span>; HandleIndex &lt; HandleCount; HandleIndex++) &#123;</span><br><span class="line">    Status = gBS-&gt;OpenProtocol(HandleBuffer[HandleIndex],</span><br><span class="line">                               &amp;gEfiSimpleFileSystemProtocolGuid,</span><br><span class="line">                               (VOID **)&amp;SimpleFileSystem, gImageHandle, <span class="literal">NULL</span>,</span><br><span class="line">                               EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);</span><br><span class="line">    <span class="keyword">if</span> (EFI_ERROR(Status)) &#123;</span><br><span class="line">      Print(<span class="string">L&quot;Open SimpleFileSystemProtocol error, at HandleIndex %d&quot;</span>,</span><br><span class="line">            HandleIndex);</span><br><span class="line">      <span class="keyword">continue</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Status = SimpleFileSystem-&gt;OpenVolume(SimpleFileSystem, &amp;Root);</span><br><span class="line">    <span class="keyword">if</span> (EFI_ERROR(Status)) &#123;</span><br><span class="line">      Print(<span class="string">L&quot;Open Root Volume error at HandleIndex %d&quot;</span>, HandleIndex);</span><br><span class="line">      gBS-&gt;CloseProtocol(HandleBuffer[HandleIndex],</span><br><span class="line">                         &amp;gEfiSimpleFileSystemProtocolGuid, gImageHandle, <span class="literal">NULL</span>);</span><br><span class="line">      <span class="keyword">continue</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 1. Open the file and get the file handle (FileHandle)</span></span><br><span class="line">    Status = Root-&gt;Open(Root, &amp;FileHandle, FileName, EFI_FILE_MODE_READ, <span class="number">0</span>);</span><br><span class="line">    <span class="keyword">if</span> ((FileHandle == <span class="literal">NULL</span>) || (EFI_ERROR(Status))) &#123;</span><br><span class="line">      Print(<span class="string">L&quot;Open file %s failed at HandleIndex %d\n&quot;</span>, FileName, HandleIndex);</span><br><span class="line">      Root-&gt;Close(Root);</span><br><span class="line">      gBS-&gt;CloseProtocol(HandleBuffer[HandleIndex],</span><br><span class="line">                         &amp;gEfiSimpleFileSystemProtocolGuid, gImageHandle, <span class="literal">NULL</span>);</span><br><span class="line">      <span class="keyword">continue</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// else, found the target handle</span></span><br><span class="line">    Print(<span class="string">L&quot;FileHandle: 0x%p at HandleIndex %d\n&quot;</span>, FileHandle, HandleIndex);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 2. Allocate memory for file info size</span></span><br><span class="line">    FileInfoSize = <span class="keyword">sizeof</span>(EFI_FILE_INFO) + <span class="number">1024</span>;</span><br><span class="line">    FileInfo = AllocateZeroPool(FileInfoSize);</span><br><span class="line">    <span class="keyword">if</span> (FileInfo == <span class="literal">NULL</span>) &#123;</span><br><span class="line">      Print(<span class="string">L&quot;Cannot allocate %d size for FileInfo at HandleIndex %d\n&quot;</span>,</span><br><span class="line">            FileInfoSize, HandleIndex);</span><br><span class="line">      FileHandle-&gt;Close(FileHandle);</span><br><span class="line">      Root-&gt;Close(Root);</span><br><span class="line">      gBS-&gt;CloseProtocol(HandleBuffer[HandleIndex],</span><br><span class="line">                         &amp;gEfiSimpleFileSystemProtocolGuid, gImageHandle, <span class="literal">NULL</span>);</span><br><span class="line">      <span class="keyword">continue</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 3. Retrieve file information</span></span><br><span class="line">    Status = FileHandle-&gt;GetInfo(FileHandle, &amp;gEfiFileInfoGuid, &amp;FileInfoSize,</span><br><span class="line">                                 FileInfo);</span><br><span class="line">    <span class="keyword">if</span> (EFI_ERROR(Status)) &#123;</span><br><span class="line">      Print(<span class="string">L&quot;Get FileInfo failed at HandleIndex %d\n&quot;</span>, HandleIndex);</span><br><span class="line">      FileHandle-&gt;Close(FileHandle);</span><br><span class="line">      Root-&gt;Close(Root);</span><br><span class="line">      gBS-&gt;CloseProtocol(HandleBuffer[HandleIndex],</span><br><span class="line">                         &amp;gEfiSimpleFileSystemProtocolGuid, gImageHandle, <span class="literal">NULL</span>);</span><br><span class="line">      <span class="keyword">continue</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    Print(<span class="string">L&quot;FileInfo: 0x%p\n&quot;</span>, FileInfo);</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// 4. Pre-allocate memory for file size</span></span><br><span class="line">    *FileSize = (UINTN)FileInfo-&gt;FileSize + <span class="keyword">sizeof</span>(CHAR16);</span><br><span class="line">    *FileData = AllocateZeroPool(*FileSize);</span><br><span class="line">    <span class="keyword">if</span> (*FileData == <span class="literal">NULL</span>) &#123;</span><br><span class="line">      Print(<span class="string">L&quot;Locate file data size %d failed at HandleIndex %d\n&quot;</span>, *FileSize,</span><br><span class="line">            HandleIndex);</span><br><span class="line">      FileHandle-&gt;Close(FileHandle);</span><br><span class="line">      gBS-&gt;FreePool(FileInfo);  <span class="comment">// Free FileInfo</span></span><br><span class="line">      Root-&gt;Close(Root);</span><br><span class="line">      gBS-&gt;CloseProtocol(HandleBuffer[HandleIndex],</span><br><span class="line">                         &amp;gEfiSimpleFileSystemProtocolGuid, gImageHandle, <span class="literal">NULL</span>);</span><br><span class="line">      <span class="keyword">continue</span>;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      Print(<span class="string">L&quot;Size of %s is %d\n&quot;</span>, FileName, *FileSize);</span><br><span class="line">      Print(<span class="string">L&quot;FileData: 0x%p\n&quot;</span>, *FileData);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 5. Read the file</span></span><br><span class="line">    Status = FileHandle-&gt;Read(FileHandle, FileSize, (VOID *)*FileData);</span><br><span class="line">    <span class="keyword">if</span> (EFI_ERROR(Status)) &#123;</span><br><span class="line">      Print(<span class="string">L&quot;Open %s file failed at HandleIndex %d\n&quot;</span>, FileName, HandleIndex);</span><br><span class="line">      FileHandle-&gt;Close(FileHandle);</span><br><span class="line">      gBS-&gt;FreePool(FileInfo);  <span class="comment">// Free FileInfo</span></span><br><span class="line">      Root-&gt;Close(Root);</span><br><span class="line">      gBS-&gt;CloseProtocol(HandleBuffer[HandleIndex],</span><br><span class="line">                         &amp;gEfiSimpleFileSystemProtocolGuid, gImageHandle, <span class="literal">NULL</span>);</span><br><span class="line">      <span class="comment">// gBS-&gt;FreePool((VOID *)FileData);</span></span><br><span class="line">      <span class="keyword">continue</span>;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      Print(<span class="string">L&quot;Open %s file success at HandleIndex %d\n&quot;</span>, FileName, HandleIndex);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    FileHandle-&gt;Close(FileHandle);</span><br><span class="line">    Print(<span class="string">L&quot;FileHandle is freed normally at HandleIndex %d\n&quot;</span>, HandleIndex);</span><br><span class="line">    gBS-&gt;FreePool(FileInfo);  <span class="comment">// Free FileInfo</span></span><br><span class="line">    Print(<span class="string">L&quot;FileInfo is freed normally at HandleIndex %d\n&quot;</span>, HandleIndex);</span><br><span class="line">    Root-&gt;Close(Root);</span><br><span class="line">    gBS-&gt;CloseProtocol(HandleBuffer[HandleIndex],</span><br><span class="line">                       &amp;gEfiSimpleFileSystemProtocolGuid, gImageHandle, <span class="literal">NULL</span>);</span><br><span class="line">    Print(<span class="string">L&quot;Operation Success at HandleIndex %d\n&quot;</span>, HandleIndex);</span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (HandleBuffer != <span class="literal">NULL</span>) &#123;</span><br><span class="line">    gBS-&gt;FreePool(HandleBuffer);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> Status;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="HandleProtocol"><a href="#HandleProtocol" class="headerlink" title="HandleProtocol"></a>HandleProtocol</h1><p>UEFI_Spec_2.8</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250201214538747.png" alt="HandleProtocol的原型" loading="lazy"></p><p>相比于OpenProtocol，不需要指定参数AgentHandle,ControllerHandle和Attributes</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  Queries a handle to determine if it supports a specified protocol.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @param[in]   Handle           The handle being queried.</span></span><br><span class="line"><span class="comment">  @param[in]   Protocol         The published unique identifier of the protocol.</span></span><br><span class="line"><span class="comment">  @param[out]  Interface        Supplies the address where a pointer to the corresponding Protocol</span></span><br><span class="line"><span class="comment">                                Interface is returned.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @retval EFI_SUCCESS           The interface information for the specified protocol was returned.</span></span><br><span class="line"><span class="comment">  @retval EFI_UNSUPPORTED       The device does not support the specified protocol.</span></span><br><span class="line"><span class="comment">  @retval EFI_INVALID_PARAMETER Handle is NULL.</span></span><br><span class="line"><span class="comment">  @retval EFI_INVALID_PARAMETER Protocol is NULL.</span></span><br><span class="line"><span class="comment">  @retval EFI_INVALID_PARAMETER Interface is NULL.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">typedef</span></span><br><span class="line"><span class="title function_">EFI_STATUS</span></span><br><span class="line"><span class="params">(EFIAPI *EFI_HANDLE_PROTOCOL)</span><span class="params">(</span></span><br><span class="line"><span class="params">  IN  EFI_HANDLE               Handle,</span></span><br><span class="line"><span class="params">  IN  EFI_GUID                 *Protocol,</span></span><br><span class="line"><span class="params">  OUT VOID                     **Interface</span></span><br><span class="line"><span class="params">  )</span>;</span><br></pre></td></tr></table></figure><p>Example：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/DevicePathLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/UefiBootServicesTableLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/UefiLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Protocol/LoadedImage.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Uefi.h&gt;</span></span></span><br><span class="line"></span><br><span class="line">EFI_STATUS EFIAPI <span class="title function_">UefiMain</span><span class="params">(IN EFI_HANDLE ImageHandle,</span></span><br><span class="line"><span class="params">                           IN EFI_SYSTEM_TABLE *SystemTable)</span> &#123;</span><br><span class="line">  EFI_STATUS Status;</span><br><span class="line">  EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;</span><br><span class="line">  Status = gBS-&gt;HandleProtocol(ImageHandle, &amp;gEfiLoadedImageProtocolGuid,</span><br><span class="line">                               (VOID **)&amp;LoadedImage);</span><br><span class="line">  <span class="keyword">if</span> (Status == EFI_SUCCESS) &#123;</span><br><span class="line">    EFI_DEVICE_PATH_PROTOCOL *DevicePath;</span><br><span class="line">    Status =</span><br><span class="line">        gBS-&gt;HandleProtocol(ImageHandle, &amp;gEfiLoadedImageDevicePathProtocolGuid,</span><br><span class="line">                            (VOID **)&amp;DevicePath);</span><br><span class="line">    <span class="keyword">if</span>(Status == EFI_SUCCESS)&#123;</span><br><span class="line">      Print(<span class="string">L&quot;Image device: %s\n&quot;</span>,ConvertDevicePathToText(DevicePath,FALSE,TRUE));</span><br><span class="line">      Print(<span class="string">L&quot;Image file: %s\n&quot;</span>, ConvertDevicePathToText(LoadedImage-&gt;FilePath,FALSE,TRUE));</span><br><span class="line">      Print(<span class="string">L&quot;Image Base: %X\n&quot;</span>,LoadedImage-&gt;ImageBase);</span><br><span class="line">      Print(<span class="string">L&quot;Image Size: %X\n&quot;</span>,LoadedImage-&gt;ImageSize);</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">      Print(<span class="string">L&quot;Can&#x27;t get EFI_LOADED_IMAGE_PROTOCOL, Status=%r\n&quot;</span>,Status);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">    Print(<span class="string">L&quot;Can&#x27;t get EFI_DEVICE_PATH_PROTOCOL, Status=%r\n&quot;</span>,Status);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> EFI_SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="ProtocolsPerHandle"><a href="#ProtocolsPerHandle" class="headerlink" title="ProtocolsPerHandle"></a>ProtocolsPerHandle</h1><p>UEFI_Spec_2.8</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250202231208653.png" alt="ProtocolsPerHandle" loading="lazy"></p><p>Retrieve the interface installed on a device handle by using the Protocol GUID.</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated</span></span><br><span class="line"><span class="comment">  from pool.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @param[in]   Handle              The handle from which to retrieve the list of protocol interface</span></span><br><span class="line"><span class="comment">                                   GUIDs.</span></span><br><span class="line"><span class="comment">  @param[out]  ProtocolBuffer      A pointer to the list of protocol interface GUID pointers that are</span></span><br><span class="line"><span class="comment">                                   installed on Handle.</span></span><br><span class="line"><span class="comment">  @param[out]  ProtocolBufferCount A pointer to the number of GUID pointers present in</span></span><br><span class="line"><span class="comment">                                   ProtocolBuffer.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @retval EFI_SUCCESS           The list of protocol interface GUIDs installed on Handle was returned in</span></span><br><span class="line"><span class="comment">                                ProtocolBuffer. The number of protocol interface GUIDs was</span></span><br><span class="line"><span class="comment">                                returned in ProtocolBufferCount.</span></span><br><span class="line"><span class="comment">  @retval EFI_OUT_OF_RESOURCES  There is not enough pool memory to store the results.</span></span><br><span class="line"><span class="comment">  @retval EFI_INVALID_PARAMETER Handle is NULL.</span></span><br><span class="line"><span class="comment">  @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.</span></span><br><span class="line"><span class="comment">  @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.</span></span><br><span class="line"><span class="comment">  @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">typedef</span></span><br><span class="line"><span class="title function_">EFI_STATUS</span></span><br><span class="line"><span class="params">(EFIAPI *EFI_PROTOCOLS_PER_HANDLE)</span><span class="params">(</span></span><br><span class="line"><span class="params">  IN  EFI_HANDLE      Handle,</span></span><br><span class="line"><span class="params">  OUT EFI_GUID        ***ProtocolBuffer,</span></span><br><span class="line"><span class="params">  OUT UINTN           *ProtocolBufferCount</span></span><br><span class="line"><span class="params">  )</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>Example:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/UefiLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/UefiBootServicesTableLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/MemoryAllocationLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Uefi.h&gt;</span></span></span><br><span class="line"></span><br><span class="line">EFI_STATUS</span><br><span class="line">EFIAPI</span><br><span class="line"><span class="title function_">UefiMain</span><span class="params">(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)</span> &#123;</span><br><span class="line">  Print(<span class="string">L&quot;_______________\n&quot;</span>);</span><br><span class="line">  EFI_GUID **ProtocolGuidArray;</span><br><span class="line">  UINTN ArrayCount;</span><br><span class="line">  EFI_STATUS Status = gBS-&gt;ProtocolsPerHandle(ImageHandle,&amp;ProtocolGuidArray,&amp;ArrayCount);</span><br><span class="line">  <span class="keyword">if</span>(Status==EFI_SUCCESS)&#123;</span><br><span class="line">    <span class="keyword">for</span>(UINTN i =<span class="number">0</span>;i&lt;ArrayCount;i++)&#123;</span><br><span class="line">      Print(<span class="string">L&quot;%g\n&quot;</span>,ProtocolGuidArray[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    FreePool(ProtocolGuidArray);</span><br><span class="line">  &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">    Print(<span class="string">L&quot;ProtocolsPerHandle error: %r\n&quot;</span>,Status);<span class="comment">//%r Print EFI_STATUS error code</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> EFI_SUCCESS;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="LocateProtocol"><a href="#LocateProtocol" class="headerlink" title="LocateProtocol"></a>LocateProtocol</h1><p>UEFI_Spec_2.8</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250225140716252.png" loading="lazy"></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250225141031426.png" alt="LocateProtocol" loading="lazy"></p><p>Unlike HandleProtocol and OpenProtocol, LocateProtocol does not care which device the protocol is on. It sequentially searches through the system’s handle list and returns the first instance of the protocol it finds.</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  Returns the first protocol instance that matches the given protocol.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @param[in]  Protocol          Provides the protocol to search for.</span></span><br><span class="line"><span class="comment">  @param[in]  Registration      Optional registration key returned from</span></span><br><span class="line"><span class="comment">                                RegisterProtocolNotify().</span></span><br><span class="line"><span class="comment">  @param[out]  Interface        On return, a pointer to the first interface that matches Protocol and</span></span><br><span class="line"><span class="comment">                                Registration.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @retval EFI_SUCCESS           A protocol instance matching Protocol was found and returned in</span></span><br><span class="line"><span class="comment">                                Interface.</span></span><br><span class="line"><span class="comment">  @retval EFI_NOT_FOUND         No protocol instances were found that match Protocol and</span></span><br><span class="line"><span class="comment">                                Registration.</span></span><br><span class="line"><span class="comment">  @retval EFI_INVALID_PARAMETER Interface is NULL.</span></span><br><span class="line"><span class="comment">                                Protocol is NULL.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">typedef</span></span><br><span class="line"><span class="title function_">EFI_STATUS</span></span><br><span class="line"><span class="params">(EFIAPI *EFI_LOCATE_PROTOCOL)</span><span class="params">(</span></span><br><span class="line"><span class="params">  IN  EFI_GUID  *Protocol,</span></span><br><span class="line"><span class="params">  IN  VOID      *Registration  OPTIONAL,</span></span><br><span class="line"><span class="params">  OUT VOID      **Interface</span></span><br><span class="line"><span class="params">  )</span>;</span><br></pre></td></tr></table></figure><p>Example:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><span class="line">EFI_STATUS</span><br><span class="line"><span class="title function_">LoadFileByName</span><span class="params">(</span></span><br><span class="line"><span class="params">IN CHAR16 *FileName,</span></span><br><span class="line"><span class="params">OUT UINT8 **FileData,</span></span><br><span class="line"><span class="params">OUT UINTN *FileSize)</span></span><br><span class="line">&#123;</span><br><span class="line">EFI_STATUS Status;</span><br><span class="line">EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;</span><br><span class="line">EFI_FILE_PROTOCOL *Root;</span><br><span class="line">EFI_FILE_PROTOCOL *FileHandle = <span class="literal">NULL</span>;</span><br><span class="line">EFI_FILE_INFO *FileInfo;</span><br><span class="line">UINTN FileInfoSize;</span><br><span class="line">UINTN TempBufferSize;</span><br><span class="line">VOID *TempBuffer;</span><br><span class="line"></span><br><span class="line">Status = gBS-&gt;LocateProtocol(&amp;gEfiSimpleFileSystemProtocolGuid,</span><br><span class="line"> <span class="literal">NULL</span>, (VOID **)&amp;SimpleFileSystem);</span><br><span class="line"><span class="keyword">if</span> (EFI_ERROR(Status))</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> Status;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Open the root directory</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line">Status = SimpleFileSystem-&gt;OpenVolume(SimpleFileSystem, &amp;Root);</span><br><span class="line"><span class="keyword">if</span> (EFI_ERROR(Status))</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> Status;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Open the file</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line">Status = Root-&gt;Open(Root, &amp;FileHandle, FileName,</span><br><span class="line">EFI_FILE_MODE_READ, <span class="number">0</span>);</span><br><span class="line"><span class="keyword">if</span> ((FileHandle == <span class="literal">NULL</span>) || (EFI_ERROR(Status)))</span><br><span class="line">&#123;</span><br><span class="line">Print(<span class="string">L&quot;Open file %s failed !!\n&quot;</span>, FileName);</span><br><span class="line">Root-&gt;Close(Root);</span><br><span class="line"><span class="keyword">return</span> Status;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Get the file information</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line">FileInfoSize = <span class="keyword">sizeof</span>(EFI_FILE_INFO) + <span class="number">1024</span>;</span><br><span class="line">FileInfo = AllocateZeroPool(FileInfoSize);</span><br><span class="line"><span class="keyword">if</span> (FileInfo == <span class="literal">NULL</span>)</span><br><span class="line">&#123;</span><br><span class="line">FileHandle-&gt;Close(FileHandle);</span><br><span class="line"><span class="keyword">return</span> Status;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Status = FileHandle-&gt;GetInfo(FileHandle, &amp;gEfiFileInfoGuid,</span><br><span class="line"> &amp;FileInfoSize,</span><br><span class="line"> FileInfo);</span><br><span class="line"><span class="keyword">if</span> (EFI_ERROR(Status))</span><br><span class="line">&#123;</span><br><span class="line">FileHandle-&gt;Close(FileHandle);</span><br><span class="line">gBS-&gt;FreePool(FileInfo);</span><br><span class="line"><span class="keyword">return</span> Status;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Allocate buffer for the file data. The last CHAR16 is for L&#x27;\0&#x27;</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line">TempBufferSize = (UINTN)FileInfo-&gt;FileSize + <span class="keyword">sizeof</span>(CHAR16);</span><br><span class="line">TempBuffer = AllocateZeroPool(TempBufferSize);</span><br><span class="line"><span class="keyword">if</span> (TempBuffer == <span class="literal">NULL</span>)</span><br><span class="line">&#123;</span><br><span class="line">FileHandle-&gt;Close(FileHandle);</span><br><span class="line">gBS-&gt;FreePool(FileInfo);</span><br><span class="line"><span class="keyword">return</span> Status;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">gBS-&gt;FreePool(FileInfo);</span><br><span class="line"></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="comment">// Read the file data to the buffer</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line">Status = FileHandle-&gt;Read(FileHandle, &amp;TempBufferSize, TempBuffer);</span><br><span class="line"><span class="keyword">if</span> (EFI_ERROR(Status))</span><br><span class="line">&#123;</span><br><span class="line">FileHandle-&gt;Close(FileHandle);</span><br><span class="line">gBS-&gt;FreePool(TempBuffer);</span><br><span class="line"><span class="keyword">return</span> Status;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">FileHandle-&gt;Close(FileHandle);</span><br><span class="line"></span><br><span class="line">*FileSize = TempBufferSize;</span><br><span class="line">*FileData = TempBuffer;</span><br><span class="line"><span class="keyword">return</span> Status;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="OpenProtocolInformation"><a href="#OpenProtocolInformation" class="headerlink" title="OpenProtocolInformation"></a>OpenProtocolInformation</h1><p>UEFI_Spec_2.8</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250225141817128.png" alt="OpenProtocolInformation" loading="lazy"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">///</span></span><br><span class="line"><span class="comment">/// EFI Oprn Protocol Information Entry</span></span><br><span class="line"><span class="comment">///</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="class"><span class="keyword">struct</span> &#123;</span></span><br><span class="line">  EFI_HANDLE    AgentHandle;</span><br><span class="line">  EFI_HANDLE    ControllerHandle;</span><br><span class="line">  UINT32        Attributes;</span><br><span class="line">  UINT32        OpenCount;</span><br><span class="line">&#125; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  Retrieves the list of agents that currently have a protocol interface opened.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @param[in]   Handle           The handle for the protocol interface that is being queried.</span></span><br><span class="line"><span class="comment">  @param[in]   Protocol         The published unique identifier of the protocol.</span></span><br><span class="line"><span class="comment">  @param[out]  EntryBuffer      A pointer to a buffer of open protocol information in the form of</span></span><br><span class="line"><span class="comment">                                EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.</span></span><br><span class="line"><span class="comment">  @param[out]  EntryCount       A pointer to the number of entries in EntryBuffer.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @retval EFI_SUCCESS           The open protocol information was returned in EntryBuffer, and the</span></span><br><span class="line"><span class="comment">                                number of entries was returned EntryCount.</span></span><br><span class="line"><span class="comment">  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to allocate EntryBuffer.</span></span><br><span class="line"><span class="comment">  @retval EFI_NOT_FOUND         Handle does not support the protocol specified by Protocol.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">typedef</span></span><br><span class="line"><span class="title function_">EFI_STATUS</span></span><br><span class="line"><span class="params">(EFIAPI *EFI_OPEN_PROTOCOL_INFORMATION)</span><span class="params">(</span></span><br><span class="line"><span class="params">  IN  EFI_HANDLE                          Handle,</span></span><br><span class="line"><span class="params">  IN  EFI_GUID                            *Protocol,</span></span><br><span class="line"><span class="params">  OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,</span></span><br><span class="line"><span class="params">  OUT UINTN                               *EntryCount</span></span><br><span class="line"><span class="params">  )</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>Example:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure><h1 id="CloseProtocol"><a href="#CloseProtocol" class="headerlink" title="CloseProtocol"></a>CloseProtocol</h1><p>UEFI_Spec_2.8</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250225142227191.png" loading="lazy"></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250225142316837.png" alt="CloseProtocol" loading="lazy"></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  Closes a protocol on a handle that was opened using OpenProtocol().</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @param[in]  Handle            The handle for the protocol interface that was previously opened</span></span><br><span class="line"><span class="comment">                                with OpenProtocol(), and is now being closed.</span></span><br><span class="line"><span class="comment">  @param[in]  Protocol          The published unique identifier of the protocol.</span></span><br><span class="line"><span class="comment">  @param[in]  AgentHandle       The handle of the agent that is closing the protocol interface.</span></span><br><span class="line"><span class="comment">  @param[in]  ControllerHandle  If the agent that opened a protocol is a driver that follows the</span></span><br><span class="line"><span class="comment">                                UEFI Driver Model, then this parameter is the controller handle</span></span><br><span class="line"><span class="comment">                                that required the protocol interface.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">  @retval EFI_SUCCESS           The protocol instance was closed.</span></span><br><span class="line"><span class="comment">  @retval EFI_INVALID_PARAMETER 1) Handle is NULL.</span></span><br><span class="line"><span class="comment">                                2) AgentHandle is NULL.</span></span><br><span class="line"><span class="comment">                                3) ControllerHandle is not NULL and ControllerHandle is not a valid EFI_HANDLE.</span></span><br><span class="line"><span class="comment">                                4) Protocol is NULL.</span></span><br><span class="line"><span class="comment">  @retval EFI_NOT_FOUND         1) Handle does not support the protocol specified by Protocol.</span></span><br><span class="line"><span class="comment">                                2) The protocol interface specified by Handle and Protocol is not</span></span><br><span class="line"><span class="comment">                                   currently open by AgentHandle and ControllerHandle.</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="keyword">typedef</span></span><br><span class="line"><span class="title function_">EFI_STATUS</span></span><br><span class="line"><span class="params">(EFIAPI *EFI_CLOSE_PROTOCOL)</span><span class="params">(</span></span><br><span class="line"><span class="params">  IN EFI_HANDLE               Handle,</span></span><br><span class="line"><span class="params">  IN EFI_GUID                 *Protocol,</span></span><br><span class="line"><span class="params">  IN EFI_HANDLE               AgentHandle,</span></span><br><span class="line"><span class="params">  IN EFI_HANDLE               ControllerHandle</span></span><br><span class="line"><span class="params">  )</span>;</span><br></pre></td></tr></table></figure><p>Example:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure><!-- flag of hidden posts -->]]></content>
    
    
    <summary type="html">A summary of methods for retrieving Protocol in EDK2 during UEFI development</summary>
    
    
    
    <category term="UEFI" scheme="https://even629.com/en/categories/UEFI/"/>
    
    
    <category term="UEFI" scheme="https://even629.com/en/tags/UEFI/"/>
    
  </entry>
  
  <entry>
    <title>Keil Installation</title>
    <link href="https://even629.com/en/posts/28522/"/>
    <id>https://even629.com/en/posts/28522/</id>
    <published>2025-01-31T11:36:13.000Z</published>
    <updated>2025-01-31T11:36:13.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="C51-Installation"><a href="#C51-Installation" class="headerlink" title="C51 Installation"></a>C51 Installation</h1><ol><li>First, visit the official website and click to download C51</li></ol>   <div class="tag link"><a class="link-card" title="Keil download" href="https://www.keil.com/download/product/"><div class="left"><img src="https://www.keil.com/images/icons/c51_dld.png"/></div><div class="right"><p class="text">Keil download</p><p class="url">https://www.keil.com/download/product/</p></div></a></div><p>You will be asked to fill out a form; just fill it out simply, then click the downloaded exe installation package to begin installation.</p><ol start="2"><li>After entering the installer, click through and confirm. For the installation location, I chose to install it on the D drive instead of the default C drive.</li></ol><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250131193502978.png" alt="C51 Installation Location" loading="lazy"></p><ol start="3"><li>Finally, click Finish to complete the installation.</li></ol><h1 id="MDK-Installation"><a href="#MDK-Installation" class="headerlink" title="MDK Installation"></a>MDK Installation</h1><p>Keil’s MDK and C51 can coexist, and the installation steps are similar.</p><ol><li>First, visit the official website to download the MDK installation package.</li></ol>   <div class="tag link"><a class="link-card" title="Keil download" href="https://www.keil.com/download/product/"><div class="left"><img src="https://www.keil.com/images/icons/mdk_dld_v2.png"/></div><div class="right"><p class="text">Keil download</p><p class="url">https://www.keil.com/download/product/</p></div></a></div><ol start="2"><li><p>During installation, set the installation location according to the location where C51 was installed.<br>   <img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250131194740287.png" alt="MDK Installation Location" loading="lazy"></p></li><li><p>Finally, click Finish to complete the installation.</p></li></ol><div class="tip warning faa-horizontal animated"><p>Note: Do not reverse the installation order of C51 and MDK</p></div><h1 id="v5-Compiler"><a href="#v5-Compiler" class="headerlink" title="v5 Compiler"></a>v5 Compiler</h1><p>First, download the v5 compiler. Since the official site seems not to offer a direct download for this version anymore, you will need to extract the v5 compiler from an older version of Keil. Below are links to pre-extracted compilers that you can download directly:</p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">Quark Cloud Drive</button><button type="button" class="tab">Baidu Cloud Drive</button></div><div class="tab-contents"><div class="tab-item-content active"><div class="tag link"><a class="link-card" title="v5 compiler download" href="https://pan.quark.cn/s/cd646c8d5b2b"><div class="left"><img src="https://image.quark.cn/s/uae/g/3o/broccoli/resource/202404/d94d93e0-03a2-11ef-be4c-79ebae2e18ac.vnd.microsoft.icon"/></div><div class="right"><p class="text">v5 compiler download</p><p class="url">https://pan.quark.cn/s/cd646c8d5b2b</p></div></a></div></div><div class="tab-item-content"><div class="tag link"><a class="link-card" title="v5 compiler download" href="https://pan.baidu.com/s/1zkUcPyKC5Z-Qda9jJb1Sjw?pwd=1234"><div class="left"><img src="https://nd-static.bdstatic.com/m-static/v20-main/favicon-main.ico"/></div><div class="right"><p class="text">v5 compiler download</p><p class="url">https://pan.baidu.com/s/1zkUcPyKC5Z-Qda9jJb1Sjw?pwd=1234</p></div></a></div></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>After downloading, unzip it to the D:\Keil_v5\ARM directory.</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250131200906926.png" alt="Compiler Extraction Directory" loading="lazy"></p><p>Open Keil, create a new project, and then click this button <strong>File Extensions, Books and Environment…</strong></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250131201214187.png" alt="File Extensions, Books and Environment..." loading="lazy"></p><p>Then click <strong>Folder&#x2F;Extensions</strong>, and click the button next to <strong>Use ARM Compiler</strong>.</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250131201435417.png" alt="Use ARM Compiler" loading="lazy"></p><p>Click <strong>Add another ARM Compiler Version to List</strong>, and select the path where you unzipped the ARMCC files.</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/image-20250131201751844.png" alt="Add another ARM Compiler Version to List" loading="lazy"></p><p>After saving, the installation is complete.</p><h1 id="References"><a href="#References" class="headerlink" title="References"></a>References</h1><div class="reference-source"><span class="hidden-anchor" id="referfrom_[1]"></span><a class="reference-anchor" href="#referto_[1]">[1]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://zhuanlan.zhihu.com/p/561047339">MDK5.37 Solution for Missing Compiler Version5</a></div>]]></content>
    
    
    <summary type="html">Keil installation, coexistence of C51 and MDK, and installation of the v5 compiler</summary>
    
    
    
    <category term="tools" scheme="https://even629.com/en/categories/tools/"/>
    
    
    <category term="Embedded tools" scheme="https://even629.com/en/tags/Embedded-tools/"/>
    
  </entry>
  
  <entry>
    <title>My Emacs Configuration</title>
    <link href="https://even629.com/en/posts/28521/"/>
    <id>https://even629.com/en/posts/28521/</id>
    <published>2025-01-12T11:36:13.000Z</published>
    <updated>2025-08-02T02:50:13.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Environment"><a href="#Environment" class="headerlink" title="Environment"></a>Environment</h1><p>Using <strong>Windows Terminal + WSL2</strong></p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo//202508021037505.png" alt="WSL2 Arch Linux" loading="lazy"></p><h1 id="Configuration"><a href="#Configuration" class="headerlink" title="Configuration"></a>Configuration</h1><h2 id="Windows-Terminal"><a href="#Windows-Terminal" class="headerlink" title="Windows Terminal"></a>Windows Terminal</h2><p>Open Windows Terminal settings, select “Open JSON file”, and add the following color scheme under <code>&quot;schemes&quot;</code>:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">&quot;schemes&quot;</span><span class="punctuation">:</span></span><br><span class="line">    <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;background&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#0D1117&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;black&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#484F58&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;blue&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#58A6FF&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;brightBlack&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#6E7681&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;brightBlue&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#79C0FF&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;brightCyan&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#56D4DD&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;brightGreen&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#56D364&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;brightPurple&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#D2A8FF&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;brightRed&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#FFA198&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;brightWhite&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#FFFFFF&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;brightYellow&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#E3B341&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;cursorColor&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#2F81F7&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;cyan&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#39C5CF&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;foreground&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#E6EDF3&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;green&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#3FB950&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;GitHub-Dark-Default&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;purple&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#BC8CFF&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;red&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#FF7B72&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;selectionBackground&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#E6EDF3&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;white&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#B1BAC4&quot;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="attr">&quot;yellow&quot;</span><span class="punctuation">:</span> <span class="string">&quot;#D29922&quot;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line"></span><br><span class="line">- In your Arch Linux profile under Appearance<span class="punctuation">:</span></span><br><span class="line">  - Set the color scheme to GitHub-Dark-Default</span><br><span class="line">  - Use the FiraCode Nerd Font</span><br><span class="line">  - Set background opacity to <span class="number">86</span>% and enable Acrylic effect</span><br><span class="line">  - In the Advanced tab<span class="punctuation">:</span></span><br><span class="line">  - Disable sound notifications<span class="punctuation">,</span> enable window flash and taskbar flash instead</span><br><span class="line"></span><br><span class="line">## Arch Linux</span><br><span class="line"></span><br><span class="line">Install necessary packages<span class="punctuation">:</span></span><br><span class="line">```bash</span><br><span class="line"># Install emacs-nox</span><br><span class="line">sudo pacman -Sy emacs-nox</span><br><span class="line"></span><br><span class="line">pacman -Sy emacs-nox</span><br><span class="line"></span><br><span class="line">pacman -Sy clang clangd clang-format rust-analyzer</span><br><span class="line"></span><br><span class="line"># After installing Rust<span class="punctuation">:</span></span><br><span class="line">rm ~/.cargo/bin/rust-analyzer</span><br><span class="line">ln -s /usr/bin/rust-analyzer ~/.cargo/bin/rust-analyzer</span><br><span class="line"></span><br><span class="line">cargo install --git https<span class="punctuation">:</span><span class="comment">//github.com/bergercookie/asm-lsp asm-lsp</span></span><br><span class="line"></span><br><span class="line"># Generate asm-lsp config file (optional)</span><br><span class="line">asm-lsp gen-config</span><br></pre></td></tr></table></figure><h2 id="Emacs-Configuration"><a href="#Emacs-Configuration" class="headerlink" title="Emacs Configuration"></a>Emacs Configuration</h2><p>Below is my .emacs configuration file. It includes support for:</p><ul><li>C&#x2F;C++, Rust, and Assembly (asm-lsp) LSP integration</li><li>Tree-sitter highlighting</li><li>Common development plugins (magit, projectile, goto-line-preview, neotree, etc.)</li><li>Clipboard sharing between WSL and Windows</li></ul><figure class="highlight lisp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br></pre></td><td class="code"><pre><span class="line">(<span class="name">menu-bar-mode</span> <span class="number">-1</span>)</span><br><span class="line"><span class="comment">;;显示行号</span></span><br><span class="line">(<span class="name">global-display-line-numbers-mode</span> <span class="literal">t</span>)</span><br><span class="line"><span class="comment">;;在ModeLine显示列号</span></span><br><span class="line">(<span class="name">add-hook</span> &#x27;prog-mode-hook &#x27;column-number-mode)</span><br><span class="line"><span class="comment">;;代码的折叠</span></span><br><span class="line">(<span class="name">add-hook</span> &#x27;prog-mode-hook &#x27;hs-minor-mode)</span><br><span class="line"><span class="comment">;; 自动重载更改的文件</span></span><br><span class="line">(<span class="name">global-auto-revert-mode</span> <span class="number">1</span>)</span><br><span class="line"><span class="comment">;; 基本设置</span></span><br><span class="line">(<span class="name">setq-default</span></span><br><span class="line"> window-combination-resize <span class="literal">t</span>                      <span class="comment">;; 新窗口平均其他左右窗口</span></span><br><span class="line"> x-stretch-cursor <span class="literal">t</span>                               <span class="comment">;; 将光标拉伸到字形宽度</span></span><br><span class="line"> )</span><br><span class="line">(<span class="name">setq</span> ring-bell-function &#x27;ignore</span><br><span class="line">      initial-scratch-message <span class="literal">nil</span></span><br><span class="line">      inhibit-startup-message <span class="literal">t</span></span><br><span class="line">      auto-save-file-name-transforms &#x27;((<span class="string">&quot;.*&quot;</span> <span class="string">&quot;~/.emacs.d/data/backup/&quot;</span> <span class="literal">t</span>)) <span class="comment">;; Write auto-save files to a separate directory</span></span><br><span class="line">      backup-directory-alist &#x27;((<span class="string">&quot;.&quot;</span> . <span class="string">&quot;~/.emacs.d/data/backup/&quot;</span>))          <span class="comment">;; Write backup files to a separate directory</span></span><br><span class="line">      create-lockfiles <span class="literal">nil</span>                                                 <span class="comment">;; Disable lockfiles as I use only one Emacs instance</span></span><br><span class="line">      scroll-conservatively <span class="number">10000</span> <span class="comment">;;防止页面滚动时跳动</span></span><br><span class="line">      undo-limit <span class="number">80000000</span>           <span class="comment">;; 提升撤销限制</span></span><br><span class="line">      display-time-default-load-average <span class="literal">nil</span> <span class="comment">;; 不显示系统负载</span></span><br><span class="line">      )</span><br><span class="line"></span><br><span class="line"><span class="comment">;; 时间显示设置</span></span><br><span class="line">(<span class="name">setq</span> display-time-24hr-format <span class="literal">t</span>   <span class="comment">;; 时间使用24小时制</span></span><br><span class="line">      display-time-day-and-date <span class="literal">t</span>   <span class="comment">;; 时间显示包括日期和具体时间</span></span><br><span class="line">      display-time-interval <span class="number">10</span>   <span class="comment">;; 时间的变化频率</span></span><br><span class="line">      display-time-format <span class="string">&quot;%Y-%m-%d %A %H:%M&quot;</span>) <span class="comment">;; 显示完整日期</span></span><br><span class="line"><span class="comment">;; 启用时间显示设置,在minibuffer上面的那个杠上</span></span><br><span class="line">(<span class="name">display-time-mode</span> <span class="number">1</span>)</span><br><span class="line"><span class="comment">;; 立即强制刷新一次时间</span></span><br><span class="line">(<span class="name">display-time-update</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">;; 使用 Fira Code Nerd Font 字体</span></span><br><span class="line">(<span class="name">set-face-attribute</span> &#x27;default <span class="literal">nil</span></span><br><span class="line">                    <span class="symbol">:font</span> <span class="string">&quot;FiraCode Nerd Font&quot;</span></span><br><span class="line">                    <span class="symbol">:height</span> <span class="number">120</span>)  <span class="comment">;; 120=12pt，可根据需求调整</span></span><br><span class="line"></span><br><span class="line"><span class="comment">;; wsl与windos共享剪切版</span></span><br><span class="line">(<span class="name">defun</span> my/clipboard-to-windows (<span class="name">text</span> <span class="symbol">&amp;optional</span> push)</span><br><span class="line">  (<span class="name">let</span> ((<span class="name">process-connection-type</span> <span class="literal">nil</span>))</span><br><span class="line">    (<span class="name">with-temp-buffer</span></span><br><span class="line">      (<span class="name">insert</span> text)</span><br><span class="line">      (<span class="name">call-process-region</span> (<span class="name">point-min</span>) (<span class="name">point-max</span>) <span class="string">&quot;win32yank.exe&quot;</span> <span class="literal">nil</span> <span class="literal">nil</span> <span class="literal">nil</span> <span class="string">&quot;-i&quot;</span>))))</span><br><span class="line"></span><br><span class="line">(<span class="name">defun</span> my/clipboard-from-windows ()</span><br><span class="line">  (<span class="name">string-trim-right</span></span><br><span class="line">   (<span class="name">with-output-to-string</span></span><br><span class="line">     (<span class="name">call-process</span> <span class="string">&quot;win32yank.exe&quot;</span> <span class="literal">nil</span> standard-output <span class="literal">nil</span> <span class="string">&quot;-o&quot;</span>))))</span><br><span class="line"></span><br><span class="line">(<span class="name">setq</span> interprogram-cut-function &#x27;my/clipboard-to-windows)</span><br><span class="line">(<span class="name">setq</span> interprogram-paste-function &#x27;my/clipboard-from-windows)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">(<span class="name">defalias</span> &#x27;yes-or-no-p &#x27;y-or-n-p)</span><br><span class="line"><span class="comment">;;不要创建备份文件</span></span><br><span class="line">(<span class="name">setq</span> make-backup-files <span class="literal">nil</span>)</span><br><span class="line"><span class="comment">;;不要创建lock文件</span></span><br><span class="line">(<span class="name">setq</span> create-lockfiles <span class="literal">nil</span>)</span><br><span class="line"><span class="comment">;; 不使用 TAB 字符，使用空格</span></span><br><span class="line">(<span class="name">setq-default</span> indent-tabs-mode <span class="literal">nil</span>)</span><br><span class="line"><span class="comment">;; tab 宽度设为 2 空格</span></span><br><span class="line">(<span class="name">setq-default</span> tab-width <span class="number">4</span>)</span><br><span class="line"><span class="comment">;; 当光标移动到边缘时，窗口每次只滚动一行</span></span><br><span class="line">(<span class="name">setq</span> scroll-step <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">;;开启可视化换行，自动折行</span></span><br><span class="line">(<span class="name">global-visual-line-mode</span> <span class="number">1</span>)</span><br><span class="line"><span class="comment">;; 主题</span></span><br><span class="line"><span class="comment">;;(load-theme &#x27;wombat t)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">;; 括号匹配</span></span><br><span class="line">(<span class="name">electric-pair-mode</span> <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">(<span class="name">add-hook</span> &#x27;prog-mode-hook &#x27;hs-minor-mode) <span class="comment">;代码的折叠</span></span><br><span class="line"></span><br><span class="line">(<span class="name">global-set-key</span> (<span class="name">kbd</span> <span class="string">&quot;C-/&quot;</span>) &#x27;undo-only)</span><br><span class="line">(<span class="name">global-set-key</span> (<span class="name">kbd</span> <span class="string">&quot;C-?&quot;</span>) &#x27;undo-redo)</span><br><span class="line"><span class="comment">;; 快捷键绑定：使用调整窗口大小</span></span><br><span class="line">(<span class="name">global-set-key</span> (<span class="name">kbd</span> <span class="string">&quot;M-&lt;up&gt;&quot;</span>)    &#x27;enlarge-window)</span><br><span class="line">(<span class="name">global-set-key</span> (<span class="name">kbd</span> <span class="string">&quot;M-&lt;down&gt;&quot;</span>)  &#x27;shrink-window)</span><br><span class="line">(<span class="name">global-set-key</span> (<span class="name">kbd</span> <span class="string">&quot;M-&lt;left&gt;&quot;</span>)  &#x27;shrink-window-horizontally)</span><br><span class="line">(<span class="name">global-set-key</span> (<span class="name">kbd</span> <span class="string">&quot;M-&lt;right&gt;&quot;</span>) &#x27;enlarge-window-horizontally)</span><br><span class="line"></span><br><span class="line"><span class="comment">;; 中文显示</span></span><br><span class="line">(<span class="name">set-language-environment</span> <span class="string">&quot;utf-8&quot;</span>)</span><br><span class="line">(<span class="name">set-buffer-file-coding-system</span> &#x27;utf-8)</span><br><span class="line">(<span class="name">set-terminal-coding-system</span> &#x27;utf-8)</span><br><span class="line">(<span class="name">set-keyboard-coding-system</span> &#x27;utf-8)</span><br><span class="line">(<span class="name">set-selection-coding-system</span> &#x27;utf-8)</span><br><span class="line">(<span class="name">set-default-coding-systems</span> &#x27;utf-8)</span><br><span class="line">(<span class="name">set-clipboard-coding-system</span> &#x27;utf-8)</span><br><span class="line">(<span class="name">modify-coding-system-alist</span> &#x27;process <span class="string">&quot;*&quot;</span> &#x27;utf-8)</span><br><span class="line">(<span class="name">prefer-coding-system</span> &#x27;utf-8)</span><br><span class="line">(<span class="name">setq-default</span> pathname-coding-system &#x27;utf-8)</span><br><span class="line">(<span class="name">setq</span></span><br><span class="line"> default-process-coding-system &#x27;(utf-8 . utf-8)</span><br><span class="line"> locale-coding-system &#x27;utf-8</span><br><span class="line"> file-name-coding-system &#x27;utf-8</span><br><span class="line"> default-buffer-file-coding-system &#x27;utf-8</span><br><span class="line"> slime-net-coding-system &#x27;utf-8-unix)</span><br><span class="line"></span><br><span class="line">(<span class="name">setenv</span> <span class="string">&quot;LC_CTYPE&quot;</span> <span class="string">&quot;UTF-8&quot;</span>)</span><br><span class="line">(<span class="name">setenv</span> <span class="string">&quot;LC_ALL&quot;</span> <span class="string">&quot;en_US.UTF-8&quot;</span>)</span><br><span class="line">(<span class="name">setenv</span> <span class="string">&quot;LANG&quot;</span> <span class="string">&quot;en_US.UTF-8&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">(<span class="name">setq</span> find-file-encoding &#x27;auto)</span><br><span class="line">(<span class="name">setq-default</span> coding-system-for-read &#x27;utf-8)</span><br><span class="line">(<span class="name">setq-default</span> coding-system-for-write &#x27;utf-8)</span><br><span class="line"></span><br><span class="line"><span class="comment">;;(setq package-archives</span></span><br><span class="line"><span class="comment">;;      &#x27;((&quot;melpa&quot; . &quot;https://melpa.org/packages/&quot;)</span></span><br><span class="line"><span class="comment">;;        (&quot;gnu&quot;   . &quot;https://elpa.gnu.org/packages/&quot;)))</span></span><br><span class="line">(<span class="name">setq</span> package-archives &#x27;((<span class="string">&quot;gnu&quot;</span>    . <span class="string">&quot;https://mirrors.tuna.tsinghua.edu.cn/elpa/gnu/&quot;</span>)</span><br><span class="line">                         (<span class="string">&quot;nongnu&quot;</span> . <span class="string">&quot;https://mirrors.tuna.tsinghua.edu.cn/elpa/nongnu/&quot;</span>)</span><br><span class="line">                         (<span class="string">&quot;melpa&quot;</span>  . <span class="string">&quot;https://mirrors.tuna.tsinghua.edu.cn/elpa/melpa/&quot;</span>)))</span><br><span class="line"></span><br><span class="line">(<span class="name">use-package</span> package</span><br><span class="line">  <span class="symbol">:config</span></span><br><span class="line">  (<span class="name">unless</span> (<span class="name">bound-and-true-p</span> package--initialized)</span><br><span class="line">    (<span class="name">package-initialize</span>)))</span><br><span class="line"></span><br><span class="line">(<span class="name">setq</span> use-package-always-ensure <span class="literal">t</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">;;doom主题</span></span><br><span class="line">(<span class="name">use-package</span> doom-themes</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:init</span></span><br><span class="line">  <span class="symbol">:config</span></span><br><span class="line">  (<span class="name">setq</span> doom-themes-enable-bold <span class="literal">t</span>    <span class="comment">; if nil, bold is universally disabled</span></span><br><span class="line">        doom-themes-enable-italic <span class="literal">t</span>) <span class="comment">; if nil, italics is universally disable</span></span><br><span class="line">  <span class="comment">;; 加载主题（例如 doom-one）</span></span><br><span class="line">  (<span class="name">load-theme</span> &#x27;doom-tomorrow-night <span class="literal">t</span>)</span><br><span class="line">  <span class="comment">;; 启用可选配置</span></span><br><span class="line">  <span class="comment">;; 高亮当前行</span></span><br><span class="line">  (<span class="name">doom-themes-visual-bell-config</span>)</span><br><span class="line">  <span class="comment">;; 改善 Org-mode 颜色</span></span><br><span class="line">  (<span class="name">doom-themes-org-config</span>))</span><br><span class="line"></span><br><span class="line">(<span class="name">defun</span> my/kill-scratch-buffer ()</span><br><span class="line">  <span class="string">&quot;在 Emacs 启动时关闭 *scratch* buffer.&quot;</span></span><br><span class="line">  (<span class="name">when</span> (<span class="name">get-buffer</span> <span class="string">&quot;*scratch*&quot;</span>)</span><br><span class="line">    (<span class="name">kill-buffer</span> <span class="string">&quot;*scratch*&quot;</span>)))</span><br><span class="line">(<span class="name">add-hook</span> &#x27;emacs-startup-hook #&#x27;my/kill-scratch-buffer)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">(<span class="name">use-package</span> centaur-tabs</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:demand</span></span><br><span class="line">  <span class="symbol">:init</span></span><br><span class="line">  <span class="symbol">:config</span></span><br><span class="line"></span><br><span class="line">  (<span class="name">defun</span> centaur-tabs-hide-tab (<span class="name">x</span>)</span><br><span class="line">    <span class="string">&quot;自定义隐藏规则：隐藏特殊或无文件 buffer.&quot;</span></span><br><span class="line">    (<span class="name">let</span> ((<span class="name">name</span> (<span class="name">format</span> <span class="string">&quot;%s&quot;</span> x)))</span><br><span class="line">      (<span class="name">or</span></span><br><span class="line">       <span class="comment">;; 无文件 buffer 一律隐藏</span></span><br><span class="line">       (<span class="name">not</span> (<span class="name">buffer-file-name</span> x))</span><br><span class="line">       <span class="comment">;; 专用窗口</span></span><br><span class="line">       (<span class="name">window-dedicated-p</span> (<span class="name">selected-window</span>))</span><br><span class="line">       <span class="comment">;; 临时 buffer</span></span><br><span class="line">       (<span class="name">string-prefix-p</span> <span class="string">&quot;*&quot;</span> name)</span><br><span class="line">       (<span class="name">string-prefix-p</span> <span class="string">&quot; &quot;</span> name)</span><br><span class="line">       <span class="comment">;; Magit 非文件 buffer</span></span><br><span class="line">       (<span class="name">and</span> (<span class="name">string-prefix-p</span> <span class="string">&quot;magit&quot;</span> name)</span><br><span class="line">            (<span class="name">not</span> (<span class="name">file-name-extension</span> name))))))</span><br><span class="line"></span><br><span class="line">  (<span class="name">setq</span> centaur-tabs-style <span class="string">&quot;bar&quot;</span></span><br><span class="line">        centaur-tabs-set-bar &#x27;over</span><br><span class="line">        centaur-tabs-modified-marker <span class="string">&quot;*&quot;</span></span><br><span class="line">        centaur-tabs-enable-key-bindings <span class="literal">nil</span></span><br><span class="line">        centaur-tabs-set-icons <span class="literal">t</span></span><br><span class="line">        centaur-tabs-icon-type &#x27;nerd-icons</span><br><span class="line">        centaur-tabs-set-close-button <span class="literal">nil</span></span><br><span class="line">        centaur-tabs-show-new-tab-button <span class="literal">nil</span></span><br><span class="line">        centaur-tabs-cycle-scope &#x27;tabs)</span><br><span class="line">  <span class="comment">;;启用插件</span></span><br><span class="line">  (<span class="name">centaur-tabs-mode</span> <span class="literal">t</span>)</span><br><span class="line">  <span class="symbol">:bind</span></span><br><span class="line">  (<span class="string">&quot;C-&lt;left&gt;&quot;</span> . centaur-tabs-backward)</span><br><span class="line">  (<span class="string">&quot;C-&lt;right&gt;&quot;</span> . centaur-tabs-forward))</span><br><span class="line"><span class="comment">;; modeline主题</span></span><br><span class="line">(<span class="name">use-package</span> doom-modeline</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:after</span> nyan-mode</span><br><span class="line">  <span class="symbol">:custom</span></span><br><span class="line">  (<span class="name">doom-modeline-buffer-file-name-style</span> &#x27;truncate-all)</span><br><span class="line">  <span class="symbol">:init</span> (<span class="name">doom-modeline-mode</span> <span class="number">1</span>))</span><br><span class="line"><span class="comment">;;显示进度条</span></span><br><span class="line">(<span class="name">use-package</span> nyan-mode</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:init</span></span><br><span class="line">  (<span class="name">nyan-mode</span> <span class="number">1</span>))</span><br><span class="line"><span class="comment">;;预览要跳转的行</span></span><br><span class="line">(<span class="name">use-package</span> goto-line-preview <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:bind</span> ((<span class="string">&quot;M-g g&quot;</span> . goto-line-preview)))</span><br><span class="line"></span><br><span class="line">(<span class="name">use-package</span> neotree</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:bind</span> ((<span class="string">&quot;C-x t&quot;</span> . neotree-toggle))</span><br><span class="line">  <span class="symbol">:config</span></span><br><span class="line">  (<span class="name">setq</span> neo-theme &#x27;arrow)</span><br><span class="line">  (<span class="name">setq</span> neo-smart-open <span class="literal">t</span>)       <span class="comment">;;  打开时自动跳到当前文件路径</span></span><br><span class="line">  (<span class="name">setq</span> neo-show-hidden-files <span class="literal">t</span>)<span class="comment">;;  显示隐藏文件</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">;;代码整行上移下移</span></span><br><span class="line">(<span class="name">use-package</span> move-dup</span><br><span class="line">  <span class="symbol">:bind</span> ((<span class="string">&quot;M-p&quot;</span>   . move-dup-move-lines-up)</span><br><span class="line">     <span class="comment">;;    (&quot;C-M-p&quot; . move-dup-duplicate-up)</span></span><br><span class="line">         (<span class="string">&quot;M-n&quot;</span>   . move-dup-move-lines-down)</span><br><span class="line">     <span class="comment">;;    (&quot;C-M-n&quot; . move-dup-duplicate-down)</span></span><br><span class="line">         ))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">(<span class="name">use-package</span> exec-path-from-shell</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:config</span></span><br><span class="line">  (<span class="name">when</span> (<span class="name">memq</span> window-system &#x27;(mac ns x))</span><br><span class="line">    (<span class="name">exec-path-from-shell-initialize</span>)))</span><br><span class="line"></span><br><span class="line"><span class="comment">;; Git工具</span></span><br><span class="line">(<span class="name">use-package</span> magit</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:defer</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:bind</span> ((<span class="string">&quot;C-x g&quot;</span> . magit-status))</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">(<span class="name">use-package</span> tree-sitter</span><br><span class="line">  <span class="symbol">:when</span> (<span class="name">and</span> (<span class="name">fboundp</span> &#x27;treesit-available-p)</span><br><span class="line">             (<span class="name">treesit-available-p</span>))</span><br><span class="line">  <span class="symbol">:config</span> (<span class="name">setq</span> treesit-font-lock-level <span class="number">4</span>)</span><br><span class="line">  <span class="symbol">:init</span></span><br><span class="line">  (<span class="name">setq</span> treesit-language-source-alist</span><br><span class="line">        &#x27;((bash       . (<span class="string">&quot;https://github.com/tree-sitter/tree-sitter-bash&quot;</span>))</span><br><span class="line">          (c          . (<span class="string">&quot;https://github.com/tree-sitter/tree-sitter-c&quot;</span>))</span><br><span class="line">          (cpp        . (<span class="string">&quot;https://github.com/tree-sitter/tree-sitter-cpp&quot;</span>))</span><br><span class="line">          (python     . (<span class="string">&quot;https://github.com/tree-sitter/tree-sitter-python&quot;</span>))</span><br><span class="line">          (rust       . (<span class="string">&quot;https://github.com/tree-sitter/tree-sitter-rust&quot;</span>))</span><br><span class="line">          (toml       . (<span class="string">&quot;https://github.com/tree-sitter/tree-sitter-toml&quot;</span>))</span><br><span class="line">          (elisp      . (<span class="string">&quot;https://github.com/Wilfred/tree-sitter-elisp&quot;</span>))</span><br><span class="line">          (cmake      . (<span class="string">&quot;https://github.com/uyha/tree-sitter-cmake&quot;</span>))</span><br><span class="line">          (dockerfile . (<span class="string">&quot;https://github.com/camdencheek/tree-sitter-dockerfile&quot;</span>))</span><br><span class="line">          (make       . (<span class="string">&quot;https://github.com/alemuller/tree-sitter-make&quot;</span>))</span><br><span class="line">          (yaml       . (<span class="string">&quot;https://github.com/ikatyang/tree-sitter-yaml&quot;</span>))</span><br><span class="line">          (json       . (<span class="string">&quot;https://github.com/tree-sitter/tree-sitter-json&quot;</span>))</span><br><span class="line">          (java       . (<span class="string">&quot;https://github.com/tree-sitter/tree-sitter-java.git&quot;</span>))</span><br><span class="line">          (markdown   . (<span class="string">&quot;https://github.com/MDeiml/tree-sitter-markdown&quot;</span> <span class="literal">nil</span> <span class="string">&quot;tree-sitter-markdown/src&quot;</span>))</span><br><span class="line">          ))</span><br><span class="line"></span><br><span class="line">  <span class="comment">;;没有内置&lt;languate&gt;-mode的需要添加</span></span><br><span class="line">  (<span class="name">add-to-list</span> &#x27;auto-mode-alist &#x27;(<span class="string">&quot;\\.y[a]?ml\\&#x27;&quot;</span> . yaml-mode))</span><br><span class="line">  (<span class="name">add-to-list</span> &#x27;auto-mode-alist &#x27;(<span class="string">&quot;\\(?:Dockerfile\\(?:\\..*\\)?\\|\\.[Dd]ockerfile\\)\\&#x27;&quot;</span> . dockerfile-mode))</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">;; 安装 tree-sitter 语法解析器（仅 Emacs 29+）</span></span><br><span class="line">(<span class="name">dolist</span> (<span class="name">lang</span> &#x27;(bash c cpp python rust toml elisp cmake dockerfile make yaml json java markdown))</span><br><span class="line">  (<span class="name">unless</span> (<span class="name">treesit-language-available-p</span> lang)</span><br><span class="line">    (<span class="name">treesit-install-language-grammar</span> lang)))</span><br><span class="line"></span><br><span class="line"><span class="comment">;; 优先使用 Tree-sitter mode</span></span><br><span class="line">(<span class="name">setq</span> major-mode-remap-alist</span><br><span class="line">      &#x27;((bash-mode        . bash-ts-mode)</span><br><span class="line">        (c-mode           . c-ts-mode)</span><br><span class="line">        (c++-mode         . c++-ts-mode)</span><br><span class="line">        (python-mode      . python-ts-mode)</span><br><span class="line">        (rust-mode        . rust-ts-mode)</span><br><span class="line">        (conf-toml-mode   . toml-ts-mode)</span><br><span class="line">        (elisp-mode  . elisp-ts-mode)</span><br><span class="line">        (cmake-mode       . cmake-ts-mode)</span><br><span class="line">        (dockerfile-mode  . dockerfile-ts-mode)</span><br><span class="line">        (json-mode        . json-ts-mode)</span><br><span class="line">        (java-mode        . java-ts-mode)</span><br><span class="line">        (yaml-mode        . yaml-ts-mode)</span><br><span class="line">        (makefile-mode    . make-ts-mode))</span><br><span class="line">      )</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">(<span class="name">require</span> &#x27;eglot)</span><br><span class="line"></span><br><span class="line">(<span class="name">setq</span> eglot-server-programs</span><br><span class="line">      &#x27;(((c++-mode c-mode c++-ts-mode c-ts-mode) . (<span class="string">&quot;clangd&quot;</span>))</span><br><span class="line">        ((rust-mode rust-ts-mode)       . (<span class="string">&quot;rust-analyzer&quot;</span>))</span><br><span class="line">        ((asm-mode nasm-mode) . (<span class="string">&quot;asm-lsp&quot;</span>))</span><br><span class="line">        ;;((markdown-mode)   . (<span class="string">&quot;ltex-ls&quot;</span>))</span><br><span class="line">        ))</span><br><span class="line"></span><br><span class="line"><span class="comment">;; eglot快捷键</span></span><br><span class="line"></span><br><span class="line">(<span class="name">global-set-key</span> (<span class="name">kbd</span> <span class="string">&quot;M-,&quot;</span>) &#x27;xref-find-definitions)  <span class="comment">;; 跳转到定义</span></span><br><span class="line">(<span class="name">global-set-key</span> (<span class="name">kbd</span> <span class="string">&quot;M-.&quot;</span>) &#x27;xref-pop-marker-stack)  <span class="comment">;; 跳回</span></span><br><span class="line">(<span class="name">global-set-key</span> (<span class="name">kbd</span> <span class="string">&quot;M-?&quot;</span>) &#x27;xref-find-references)   <span class="comment">;; 查找引用</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">;;自动打开eglot</span></span><br><span class="line">(<span class="name">add-hook</span> &#x27;c-mode-hook &#x27;eglot-ensure)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;c-ts-mode-hook &#x27;eglot-ensure)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;c++-mode-hook &#x27;eglot-ensure)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;c++-ts-mode-hook &#x27;eglot-ensure)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;rust-mode-hook &#x27;eglot-ensure)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;rust-ts-mode-hook &#x27;eglot-ensure)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;asm-mode-hook &#x27;eglot-ensure)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;nasm-mode-hook &#x27;eglot-ensure)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">;;(add-hook &#x27;markdown-mode-hook &#x27;eglot-ensure)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">;;(setq eglot-ignored-server-capabilities &#x27;(:textDocument/hover))</span></span><br><span class="line"><span class="comment">;;(setq eglot-timeout 10)  ;; 增加超时时间，单位为秒</span></span><br><span class="line"></span><br><span class="line"><span class="comment">;; comment</span></span><br><span class="line">(<span class="name">defun</span> my-cpp-line-comments ()</span><br><span class="line">  <span class="string">&quot;Use // comments instead of /* */ in C/C++.&quot;</span></span><br><span class="line">  (<span class="name">setq-local</span> comment-start <span class="string">&quot;// &quot;</span></span><br><span class="line">              comment-end <span class="string">&quot;&quot;</span></span><br><span class="line">              comment-start-skip <span class="string">&quot;//+\\s-*&quot;</span>))</span><br><span class="line"></span><br><span class="line">(<span class="name">add-hook</span> &#x27;c-mode-hook #&#x27;my-cpp-line-comments)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;c++-mode-hook #&#x27;my-cpp-line-comments)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;c-ts-mode-hook #&#x27;my-cpp-line-comments)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;c++-ts-mode-hook #&#x27;my-cpp-line-comments)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;rust-mode-hook #&#x27;my-cpp-line-comments)</span><br><span class="line">(<span class="name">add-hook</span> &#x27;rust-ts-mode-hook #&#x27;my-cpp-line-comments)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">(<span class="name">use-package</span> company <span class="symbol">:ensure</span> <span class="literal">t</span> <span class="symbol">:defer</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:hook</span> (<span class="name">after-init</span> . global-company-mode))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">(<span class="name">use-package</span> format-all</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:commands</span> format-all-mode</span><br><span class="line">  <span class="symbol">:hook</span> (<span class="name">prog-mode</span> . format-all-mode)</span><br><span class="line">  <span class="symbol">:config</span></span><br><span class="line">  (<span class="name">setq-default</span> format-all-formatters</span><br><span class="line">                &#x27;((<span class="string">&quot;C&quot;</span> (clang-format))</span><br><span class="line">                  (<span class="string">&quot;C++&quot;</span>     (clang-format))</span><br><span class="line">                  (<span class="string">&quot;rust&quot;</span> (rustfmt))</span><br><span class="line">                  )))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">(<span class="name">global-set-key</span> (<span class="name">kbd</span> <span class="string">&quot;C-x f&quot;</span>) &#x27;format-all-buffer)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">;; which-key 显示键绑定提示</span></span><br><span class="line">(<span class="name">use-package</span> which-key</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:config</span></span><br><span class="line">  (<span class="name">which-key-mode</span>))</span><br><span class="line"><span class="comment">;; 窗格切换</span></span><br><span class="line">(<span class="name">use-package</span> ace-window</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:bind</span> ((<span class="string">&quot;M-o&quot;</span> . ace-window)))</span><br><span class="line"><span class="comment">;; 窗格移动</span></span><br><span class="line">(<span class="name">use-package</span> buffer-move</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:bind</span> ((<span class="string">&quot;C-c &lt;up&gt;&quot;</span>    . buf-move-up)</span><br><span class="line">         (<span class="string">&quot;C-c &lt;down&gt;&quot;</span>  . buf-move-down)</span><br><span class="line">         (<span class="string">&quot;C-c &lt;left&gt;&quot;</span>  . buf-move-left)</span><br><span class="line">         (<span class="string">&quot;C-c &lt;right&gt;&quot;</span> . buf-move-right)))</span><br><span class="line"><span class="comment">;; 智能按键C-a C-c k</span></span><br><span class="line">(<span class="name">use-package</span> crux</span><br><span class="line">  <span class="symbol">:bind</span> ((<span class="string">&quot;C-a&quot;</span> . &#x27;crux-move-beginning-of-line)</span><br><span class="line">         (<span class="string">&quot;C-c k&quot;</span> . &#x27;crux-smart-kill-line)))</span><br><span class="line"><span class="comment">;; 项目识别,通过创建.projectile文件识别为一个项目</span></span><br><span class="line">(<span class="name">use-package</span> projectile</span><br><span class="line">  <span class="symbol">:ensure</span> <span class="literal">t</span></span><br><span class="line">  <span class="symbol">:init</span></span><br><span class="line">  (<span class="name">projectile-mode</span> <span class="number">+1</span>)</span><br><span class="line">  <span class="symbol">:bind-keymap</span></span><br><span class="line">  (<span class="string">&quot;C-c p&quot;</span> . projectile-command-map)</span><br><span class="line">  <span class="symbol">:config</span></span><br><span class="line">  (<span class="name">setq</span> projectile-project-search-path &#x27;(<span class="string">&quot;~/repository&quot;</span>))</span><br><span class="line">  (<span class="name">setq</span> projectile-completion-system &#x27;auto))  <span class="comment">;; 或 ivy / helm / default</span></span><br><span class="line"></span><br><span class="line"><span class="comment">;; (defun my-vscode-layout ()</span></span><br><span class="line"><span class="comment">;;   &quot;Neotree 左侧，右侧上下分为代码和 eshell，放大代码窗口，焦点回代码。&quot;</span></span><br><span class="line"><span class="comment">;;   (interactive)</span></span><br><span class="line"><span class="comment">;;   (let ((orig-buffer (current-buffer)))</span></span><br><span class="line"><span class="comment">;;     ;; 删除所有窗口，统一布局</span></span><br><span class="line"><span class="comment">;;     (delete-other-windows)</span></span><br><span class="line"><span class="comment">;;     ;; 打开 Neotree（会自动左右分割）</span></span><br><span class="line"><span class="comment">;;     (neotree-show)</span></span><br><span class="line"><span class="comment">;;     ;; 选中右侧工作区</span></span><br><span class="line"><span class="comment">;;     (select-window (next-window))</span></span><br><span class="line"><span class="comment">;;     ;; 上下分割：上是代码，下是 eshell</span></span><br><span class="line"><span class="comment">;;     (split-window-below)</span></span><br><span class="line"><span class="comment">;;     ;; 当前是上窗口，记录下来</span></span><br><span class="line"><span class="comment">;;     (let ((code-win (selected-window)))</span></span><br><span class="line"><span class="comment">;;       ;; 选中下窗口并打开 eshell</span></span><br><span class="line"><span class="comment">;;       (other-window 1)</span></span><br><span class="line"><span class="comment">;;       (eshell)</span></span><br><span class="line"><span class="comment">;;       ;; 回到上窗口并还原 buffer</span></span><br><span class="line"><span class="comment">;;       (select-window code-win)</span></span><br><span class="line"><span class="comment">;;       (switch-to-buffer orig-buffer)</span></span><br><span class="line"><span class="comment">;;       ;; 放大代码区窗口，让 eshell 更小（例如放大 10 行）</span></span><br><span class="line"><span class="comment">;;       (enlarge-window 10)</span></span><br><span class="line"><span class="comment">;;       )))</span></span><br><span class="line"></span><br><span class="line"><span class="comment">;; (global-set-key (kbd &quot;C-c v&quot;) #&#x27;my-vscode-layout)</span></span><br><span class="line"></span><br><span class="line">(<span class="name">custom-set-variables</span></span><br><span class="line"> <span class="comment">;; custom-set-variables was added by Custom.</span></span><br><span class="line"> <span class="comment">;; If you edit it by hand, you could mess it up, so be careful.</span></span><br><span class="line"> <span class="comment">;; Your init file should contain only one such instance.</span></span><br><span class="line"> <span class="comment">;; If there is more than one, they won&#x27;t work right.</span></span><br><span class="line"> &#x27;(package-selected-packages nil))</span><br><span class="line">(<span class="name">custom-set-faces</span></span><br><span class="line"> <span class="comment">;; custom-set-faces was added by Custom.</span></span><br><span class="line"> <span class="comment">;; If you edit it by hand, you could mess it up, so be careful.</span></span><br><span class="line"> <span class="comment">;; Your init file should contain only one such instance.</span></span><br><span class="line"> <span class="comment">;; If there is more than one, they won&#x27;t work right.</span></span><br><span class="line"> )</span><br></pre></td></tr></table></figure><h1 id="Preview"><a href="#Preview" class="headerlink" title="Preview"></a>Preview</h1><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo//202508021054338.png" alt="preview" loading="lazy"></p><h1 id="Keybindings-Overview"><a href="#Keybindings-Overview" class="headerlink" title="Keybindings Overview"></a>Keybindings Overview</h1><table><thead><tr><th>Shortcut</th><th>Description</th><th>Source</th></tr></thead><tbody><tr><td><strong>C-&#x2F;</strong></td><td>Undo (undo-only)</td><td>Custom</td></tr><tr><td><strong>C-?</strong></td><td>Redo (undo-redo)</td><td>Custom</td></tr><tr><td><strong>M-↑</strong></td><td>Increase window height</td><td>Custom</td></tr><tr><td><strong>M-↓</strong></td><td>Decrease window height</td><td>Custom</td></tr><tr><td><strong>M-←</strong></td><td>Decrease window width</td><td>Custom</td></tr><tr><td><strong>M-→</strong></td><td>Increase window width</td><td>Custom</td></tr><tr><td><strong>C-←</strong></td><td>Switch to previous tab (Centaur Tabs)</td><td><code>centaur-tabs</code></td></tr><tr><td><strong>C-→</strong></td><td>Switch to next tab</td><td><code>centaur-tabs</code></td></tr><tr><td><strong>M-g g</strong></td><td>Preview go-to-line</td><td><code>goto-line-preview</code></td></tr><tr><td><strong>M-p</strong></td><td>Move current line up</td><td><code>move-dup</code></td></tr><tr><td><strong>M-n</strong></td><td>Move current line down</td><td><code>move-dup</code></td></tr><tr><td><strong>C-x t</strong></td><td>Toggle file tree sidebar (neotree)</td><td><code>neotree</code></td></tr><tr><td><strong>C-x g</strong></td><td>Open Git status (magit-status)</td><td><code>magit</code></td></tr><tr><td><strong>M-x magit-log-all</strong></td><td>View all Git commits in the current repository</td><td><code>magit</code></td></tr><tr><td><strong>C-x f</strong></td><td>Format current buffer (clang-format &#x2F; rustfmt)</td><td><code>format-all</code></td></tr><tr><td><strong>M-,</strong></td><td>Jump to definition (xref-find-definitions, LSP)</td><td>Custom</td></tr><tr><td><strong>M-.</strong></td><td>Jump back to previous location (xref-pop-marker)</td><td>Custom</td></tr><tr><td><strong>M-?</strong></td><td>Find references (xref-find-references, LSP)</td><td>Custom</td></tr><tr><td><strong>M-o</strong></td><td>Switch between windows</td><td><code>ace-window</code></td></tr><tr><td><strong>C-c ↑</strong></td><td>Move current buffer up to another window</td><td><code>buffer-move</code></td></tr><tr><td><strong>C-c ↓</strong></td><td>Move current buffer down to another window</td><td><code>buffer-move</code></td></tr><tr><td><strong>C-c ←</strong></td><td>Move current buffer left to another window</td><td><code>buffer-move</code></td></tr><tr><td><strong>C-c →</strong></td><td>Move current buffer right to another window</td><td><code>buffer-move</code></td></tr><tr><td><strong>C-a</strong></td><td>Smart move to beginning of line</td><td><code>crux</code></td></tr><tr><td><strong>C-c k</strong></td><td>Smart kill line</td><td><code>crux</code></td></tr><tr><td><strong>C-c p</strong></td><td>Projectile command prefix</td><td><code>projectile</code></td></tr></tbody></table>]]></content>
    
    
    <summary type="html">My personal Emacs configuration for C/C++, Rust, and Assembly development, including syntax highlighting for various common file types.</summary>
    
    
    
    <category term="emacs" scheme="https://even629.com/en/categories/emacs/"/>
    
    
    <category term="emacs" scheme="https://even629.com/en/tags/emacs/"/>
    
  </entry>
  
  <entry>
    <title>Setting up a UEFI Development Environment based on edk2 in Linux</title>
    <link href="https://even629.com/en/posts/42853/"/>
    <id>https://even629.com/en/posts/42853/</id>
    <published>2025-01-10T11:18:13.000Z</published>
    <updated>2025-02-07T08:44:13.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Basic-Environment-Setup"><a href="#Basic-Environment-Setup" class="headerlink" title="Basic Environment Setup"></a>Basic Environment Setup</h1><p>This is my hardware environment and operating system.</p><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/pc_environment.png" alt="Hardware Environment" loading="lazy"></p><h2 id="Download-edk2-Source-Code"><a href="#Download-edk2-Source-Code" class="headerlink" title="Download edk2 Source Code"></a>Download edk2 Source Code</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Install required packages</span></span><br><span class="line"><span class="built_in">sudo</span> apt update</span><br><span class="line"><span class="built_in">sudo</span> apt install git</span><br><span class="line"><span class="built_in">mkdir</span> -p ~/UEFI</span><br><span class="line"><span class="built_in">cd</span> UEFI</span><br><span class="line">git <span class="built_in">clone</span> <span class="string">&quot;https://github.com/tianocore/edk2.git&quot;</span></span><br><span class="line"><span class="built_in">cd</span> edk2</span><br><span class="line"><span class="comment"># Switch to this branch</span></span><br><span class="line">git checkout origin/stable/202408</span><br><span class="line">git submodule update --init --recursive</span><br><span class="line">git branch</span><br><span class="line"><span class="comment"># Check if all submodules are initialized correctly. If not, compilation may have issues.</span></span><br><span class="line">git submodule status</span><br><span class="line"><span class="built_in">cd</span> -</span><br><span class="line"><span class="comment"># Download edk2-libc code, mainly for using the C standard library in UEFI development.</span></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/tianocore/edk2-libc.git</span><br><span class="line"><span class="comment"># Create a code folder to store our own code</span></span><br><span class="line"><span class="built_in">mkdir</span> -p code</span><br></pre></td></tr></table></figure><h2 id="Install-Compilation-Tools"><a href="#Install-Compilation-Tools" class="headerlink" title="Install Compilation Tools"></a>Install Compilation Tools</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Install basic software packages</span></span><br><span class="line"><span class="built_in">sudo</span> apt-get install python3 python3-distutils uuid-dev build-essential bison flex nasm acpica-tools gcc</span><br><span class="line"><span class="comment"># Install ARM compiler, mainly for compiling aarch64</span></span><br><span class="line"><span class="built_in">mkdir</span> -p ~/UEFI/toolchain</span><br><span class="line"><span class="built_in">cd</span> ~/UEFI/toolchain</span><br><span class="line">wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2019.01/gcc-arm-8.2-2019.01-x86_64-aarch64-elf.tar.xz</span><br><span class="line">tar -xf gcc-arm-8.2-2019.01-x86_64-aarch64-elf.tar.xz</span><br><span class="line"><span class="built_in">cd</span> -</span><br></pre></td></tr></table></figure><h1 id="HelloWorld-Example"><a href="#HelloWorld-Example" class="headerlink" title="HelloWorld Example"></a>HelloWorld Example</h1><p>Let’s implement a UEFI code compilation for the target platform x64 or aarch64, which supports running on Emulator and qemu, and debugging with gdb.</p><h2 id="Code"><a href="#Code" class="headerlink" title="Code"></a>Code</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">touch</span> HelloWorld.dsc</span><br><span class="line"><span class="built_in">touch</span> HelloWorld.inf</span><br><span class="line"><span class="built_in">touch</span> HelloWorld.c</span><br><span class="line"><span class="comment"># Use this command to generate UUID, used in dsc and inf files</span></span><br><span class="line">uuidgen</span><br></pre></td></tr></table></figure><p><strong>HelloWorld.dsc</strong></p><p>The DSC file is the package description file, where all fields in Defines are mandatory.<br>To find paths for LibraryClasses, use the following command:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> edk2</span><br><span class="line"><span class="comment"># Take UefiApplicationEntryPoint as an example</span></span><br><span class="line">grep UefiApplicationEntryPoint -r ./ --include=*.inf | grep LIBRARY_CLASS</span><br><span class="line"><span class="comment"># Find by GUID</span></span><br><span class="line">grep -i 752F3136 -r ./ --exclude-dir=Build</span><br></pre></td></tr></table></figure><p>The format for LibraryClasses is:</p><figure class="highlight toml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">LibraryClassName|Path/To/LibInstanceName.inf</span><br></pre></td></tr></table></figure><p>For a full explanation of DSC files, refer to the following link:<br>   <div class="tag link"><a class="link-card" title="INF-Specification" href="https://tianocore-docs.github.io/edk2-DscSpecification/release-1.28/"><div class="left"><img src="https://tianocore-docs.github.io/edk2-DscSpecification/release-1.28/gitbook/images/favicon.ico"/></div><div class="right"><p class="text">INF-Specification</p><p class="url">https://tianocore-docs.github.io/edk2-DscSpecification/release-1.28/</p></div></a></div></p><figure class="highlight toml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[Defines]</span></span><br><span class="line">  <span class="attr">DSC_SPECIFICATION</span>         = <span class="number">0</span>x0001001A</span><br><span class="line">  <span class="attr">PLATFORM_GUID</span>             = c08977d4-<span class="number">6</span>e87-<span class="number">42</span>f6-bf5c-<span class="number">4</span>d41cfe7ba53</span><br><span class="line">  <span class="attr">PLATFORM_VERSION</span>          = <span class="number">0.01</span></span><br><span class="line">  <span class="attr">PLATFORM_NAME</span>             = HelloWorld</span><br><span class="line">  <span class="attr">SKUID_IDENTIFIER</span>          = DEFAULT</span><br><span class="line">  <span class="attr">SUPPORTED_ARCHITECTURES</span>   = AARCH64|X64</span><br><span class="line">  <span class="attr">BUILD_TARGETS</span>             = DEBUG|RELEASE|NOOPT</span><br><span class="line">  <span class="attr">OUTPUT_DIRECTORY</span>          = $(PKG_OUTPUT_DIR)</span><br><span class="line"></span><br><span class="line"><span class="section">[LibraryClasses]</span></span><br><span class="line">  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf</span><br><span class="line">  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf</span><br><span class="line">  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf</span><br><span class="line">  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf</span><br><span class="line">  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf</span><br><span class="line">  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf</span><br><span class="line">  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf</span><br><span class="line">  ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf</span><br><span class="line">  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf</span><br><span class="line">  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf</span><br><span class="line">  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf</span><br><span class="line"></span><br><span class="line">  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf</span><br><span class="line">  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf</span><br><span class="line"></span><br><span class="line"><span class="section">[LibraryClasses.ARM,LibraryClasses.AARCH64]</span></span><br><span class="line">  NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf</span><br><span class="line">  NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf</span><br><span class="line"></span><br><span class="line"><span class="section">[LibraryClasses.X64]</span></span><br><span class="line">  RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf</span><br><span class="line"></span><br><span class="line"><span class="section">[Components]</span></span><br><span class="line">  HelloWorld.inf</span><br></pre></td></tr></table></figure><p><strong>HelloWorld.inf</strong><br>The INF file is a configuration file for an EDK2 application. It contains several sections:</p><ul><li>[Defines]: This section defines basic information for the module.<ul><li>BASE_NAME: The name of the application.</li><li>FILE_GUID: This can be generated using the uuidgen command. UEFI uses the GUID to distinguish between different modules.</li><li>MODULE_TYPE: This should be set to UEFI_APPLICATION.</li><li>ENTRY_POINT: The name of the main function in the C code.</li></ul></li><li>[Sources]: The source code for the module, typically .c and .h files.</li><li>[Packages]: The packages required by the module.</li><li>[LibraryClasses]: The libraries that the module depends on.</li></ul><p>For a complete explanation of the INF file, refer to the following link:<br>   <div class="tag link"><a class="link-card" title="INF-Specification" href="https://tianocore-docs.github.io/edk2-InfSpecification/release-1.27/"><div class="left"><img src="https://tianocore-docs.github.io/edk2-InfSpecification/release-1.27/gitbook/images/favicon.ico"/></div><div class="right"><p class="text">INF-Specification</p><p class="url">https://tianocore-docs.github.io/edk2-InfSpecification/release-1.27/</p></div></a></div></p><p>Below is an example of a simple module definition:</p><figure class="highlight toml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Variables defined to be used during the build process</span></span><br><span class="line"><span class="section">[Defines]</span></span><br><span class="line">  <span class="attr">INF_VERSION</span>       = <span class="number">1.25</span></span><br><span class="line">  <span class="attr">BASE_NAME</span>         = HelloWorld</span><br><span class="line">  <span class="attr">FILE_GUID</span>         = <span class="number">5455334</span>b-dbd9-<span class="number">4</span>f95-b6ed-<span class="number">5</span>ae261a6a0c1</span><br><span class="line">  <span class="attr">MODULE_TYPE</span>       = UEFI_APPLICATION</span><br><span class="line">  <span class="attr">VERSION_STRING</span>    = <span class="number">1.0</span></span><br><span class="line">  <span class="attr">ENTRY_POINT</span>       = UefiMain</span><br><span class="line"></span><br><span class="line"><span class="comment"># Source code</span></span><br><span class="line"><span class="section">[Sources]</span></span><br><span class="line">  HelloWorld.c</span><br><span class="line"></span><br><span class="line"><span class="comment"># Required packages</span></span><br><span class="line"><span class="section">[Packages]</span></span><br><span class="line">  MdePkg/MdePkg.dec            <span class="comment"># Contains Uefi and UefiLib</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Required Libraries</span></span><br><span class="line"><span class="section">[LibraryClasses]</span></span><br><span class="line">  UefiApplicationEntryPoint    <span class="comment"># Uefi application entry point</span></span><br><span class="line">  UefiLib                      <span class="comment"># UefiLib</span></span><br><span class="line">  UefiBootServicesTableLib</span><br></pre></td></tr></table></figure><p><strong>HelloWorld.c</strong></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/UefiLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Uefi.h&gt;</span></span></span><br><span class="line"></span><br><span class="line">EFI_STATUS</span><br><span class="line">EFIAPI</span><br><span class="line"><span class="title function_">UefiMain</span><span class="params">(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)</span> &#123;</span><br><span class="line">  Print(<span class="string">L&quot;Hello World!!!\n&quot;</span>);</span><br><span class="line">  SystemTable-&gt;BootServices-&gt;Stall(<span class="number">10000000</span>);</span><br><span class="line">  <span class="keyword">return</span> EFI_SUCCESS;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Build-Script"><a href="#Build-Script" class="headerlink" title="Build Script"></a>Build Script</h2><p>First, we need to create a script to set up the environment variables:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">touch</span> env.sh</span><br><span class="line"><span class="built_in">chmod</span> a+x env.sh</span><br></pre></td></tr></table></figure><p><strong>env.sh</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment"># Project name, also the directory of the source files</span></span><br><span class="line"><span class="built_in">export</span> PROJ_NAME=<span class="string">&quot;HelloWorld&quot;</span></span><br><span class="line"><span class="comment"># DSC file name</span></span><br><span class="line"><span class="built_in">export</span> DSC_NAME=<span class="string">&quot;HelloWorld&quot;</span></span><br><span class="line"><span class="comment"># INF file name</span></span><br><span class="line"><span class="built_in">export</span> INF_NAME=<span class="string">&quot;HelloWorld&quot;</span></span><br><span class="line"><span class="comment"># Also the name of the generated *.efi, defined in INF&#x27;s BASE_NAME</span></span><br><span class="line"><span class="built_in">export</span> INF_BASE_NAME=<span class="string">&quot;HelloWorld&quot;</span></span><br><span class="line"><span class="comment"># UEFI workspace directory</span></span><br><span class="line"><span class="built_in">export</span> UEFI_WORKSPACE=<span class="string">&quot;<span class="variable">$HOME</span>/UEFI&quot;</span></span><br><span class="line"><span class="comment"># EDK II path</span></span><br><span class="line"><span class="built_in">export</span> EDK_PATH=<span class="string">&quot;<span class="variable">$UEFI_WORKSPACE</span>/edk2&quot;</span></span><br><span class="line"><span class="comment"># EDK II libc path</span></span><br><span class="line"><span class="built_in">export</span> EDK_LIBC_PATH=<span class="string">&quot;<span class="variable">$UEFI_WORKSPACE</span>/edk2-libc&quot;</span></span><br><span class="line"><span class="comment"># Application code path</span></span><br><span class="line"><span class="built_in">export</span> APP_PATH=<span class="string">&quot;<span class="variable">$UEFI_WORKSPACE</span>/code/<span class="variable">$PROJ_NAME</span>&quot;</span></span><br><span class="line"><span class="comment"># Build output directory</span></span><br><span class="line"><span class="built_in">export</span> PKG_OUTPUT_DIR=<span class="string">&quot;<span class="variable">$APP_PATH</span>/Build&quot;</span></span><br><span class="line"><span class="comment"># Emulator path</span></span><br><span class="line"><span class="built_in">export</span> EMULATOR_PATH=<span class="string">&quot;<span class="variable">$EDK_PATH</span>/Build/EmulatorX64/DEBUG_GCC5/X64&quot;</span></span><br><span class="line"><span class="comment"># Package path settings, supports multiple paths separated by colon</span></span><br><span class="line"><span class="built_in">export</span> PACKAGES_PATH=<span class="string">&quot;<span class="variable">$EDK_PATH</span>:<span class="variable">$EDK_LIBC_PATH</span>:<span class="variable">$APP_PATH</span>&quot;</span></span><br><span class="line"><span class="comment"># Specify Python interpreter</span></span><br><span class="line"><span class="built_in">export</span> PYTHON_COMMAND=<span class="string">&quot;/usr/bin/python3&quot;</span></span><br><span class="line"><span class="comment"># Confirm that environment variables have been set</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;Environment variables for <span class="variable">$PROJ_NAME</span> project are configured.&quot;</span></span><br></pre></td></tr></table></figure><p>Next, we will write a script to compile the code for the x64 target platform.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">touch</span> build-x64.sh</span><br><span class="line"><span class="built_in">chmod</span> a+x build-x64.sh</span><br></pre></td></tr></table></figure><p><strong>build-x64.sh</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="built_in">set</span> -e</span><br><span class="line"><span class="built_in">trap</span> <span class="string">&quot;Exiting&quot;</span> INT</span><br><span class="line"></span><br><span class="line"><span class="comment"># environment variables</span></span><br><span class="line"><span class="built_in">source</span> env.sh</span><br><span class="line"></span><br><span class="line"><span class="built_in">export</span> GCC5=/usr/bin/gcc</span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$EDK_PATH</span></span><br><span class="line"><span class="built_in">source</span> edksetup.sh</span><br><span class="line"><span class="built_in">cd</span> -</span><br><span class="line"></span><br><span class="line"><span class="comment"># Building BaseTools</span></span><br><span class="line">make -C <span class="variable">$EDK_PATH</span>/BaseTools</span><br><span class="line"><span class="comment"># In this script, the -b flag is set to DEBUG. When deploying, you should use RELEASE instead.</span></span><br><span class="line"><span class="comment"># -p --platform=</span></span><br><span class="line"><span class="comment"># -m --module=</span></span><br><span class="line"><span class="comment"># -a --arch=</span></span><br><span class="line"><span class="comment"># -b --buildtarget=</span></span><br><span class="line"><span class="comment"># -t --taggname=</span></span><br><span class="line">build -p <span class="variable">$APP_PATH</span>/<span class="variable">$DSC_NAME</span>.dsc -m <span class="variable">$APP_PATH</span>/<span class="variable">$INF_NAME</span>.inf -a X64 -t GCC5 -b DEBUG -D PKG_OUTPUT_DIR=<span class="variable">$PKG_OUTPUT_DIR</span></span><br></pre></td></tr></table></figure><p>The process for compiling to the AArch64 platform is similar.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">touch</span> build-aarch64.sh</span><br><span class="line"><span class="built_in">chmod</span> a+x build-aarch64.sh</span><br></pre></td></tr></table></figure><p><strong>build-aarch64.sh</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="built_in">set</span> -e</span><br><span class="line"><span class="built_in">trap</span> <span class="string">&quot;Exiting&quot;</span> INT</span><br><span class="line"></span><br><span class="line"><span class="comment"># environment variables</span></span><br><span class="line"><span class="built_in">source</span> env.sh</span><br><span class="line"></span><br><span class="line"><span class="built_in">export</span> GCC5_AARCH64_PREFIX=<span class="variable">$UEFI_WORKSPACE</span>/toolchain/gcc-arm-8.2-2019.01-x86_64-aarch64-elf/bin/aarch64-elf-</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$EDK_PATH</span></span><br><span class="line"><span class="built_in">source</span> edksetup.sh</span><br><span class="line"><span class="built_in">cd</span> -</span><br><span class="line"></span><br><span class="line"><span class="comment"># Building BaseTools</span></span><br><span class="line">make -C <span class="variable">$EDK_PATH</span>/BaseTools</span><br><span class="line"></span><br><span class="line">build -p <span class="variable">$APP_PATH</span>/<span class="variable">$DSC_NAME</span>.dsc -m <span class="variable">$APP_PATH</span>/<span class="variable">$INF_NAME</span>.inf -a AARCH64 -t GCC5 -b DEBUG -D PKG_OUTPUT_DIR=<span class="variable">$PKG_OUTPUT_DIR</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="Running"><a href="#Running" class="headerlink" title="Running"></a>Running</h2><h3 id="Run-on-Emulator"><a href="#Run-on-Emulator" class="headerlink" title="Run on Emulator"></a>Run on Emulator</h3><p>Finally, we write a script to run on the emulator provided by edk2. Note that you need a GUI environment here. If you’re only using the command line, skip this step and refer to the next section to run with QEMU.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">touch</span> run.sh</span><br><span class="line"><span class="built_in">chmod</span> a+x run.sh</span><br></pre></td></tr></table></figure><p><strong>run.sh</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="built_in">set</span> -e</span><br><span class="line"><span class="built_in">trap</span> <span class="string">&quot;Exiting&quot;</span> INT</span><br><span class="line"></span><br><span class="line"><span class="built_in">source</span> env.sh</span><br><span class="line"></span><br><span class="line"><span class="built_in">export</span> GCC5=/usr/bin/gcc</span><br><span class="line"><span class="comment"># Emulator compilation, once compiled, no need to compile again</span></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$EDK_PATH</span></span><br><span class="line"><span class="built_in">source</span> edksetup.sh</span><br><span class="line">build -p <span class="variable">$EDK_PATH</span>/EmulatorPkg/EmulatorPkg.dsc -t GCC5 -a X64</span><br><span class="line"></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> -p <span class="variable">$EMULATOR_PATH</span>/UEFI_Disk</span><br><span class="line"></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">cp</span> <span class="variable">$APP_PATH</span>/Build/DEBUG_GCC5/X64/<span class="variable">$INF_BASE_NAME</span>.efi <span class="variable">$EMULATOR_PATH</span>/UEFI_Disk/</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$EMULATOR_PATH</span></span><br><span class="line">./Host</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="Run-with-QEMU"><a href="#Run-with-QEMU" class="headerlink" title="Run with QEMU"></a>Run with QEMU</h3><p>First, compile and install QEMU. Here, I choose version 8.1.5. If your version is not working as expected, consider using QEMU version 8.1.5.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://gitlab.com/qemu-project/qemu.git</span><br><span class="line"><span class="built_in">cd</span> qemu</span><br><span class="line">git checkout stable-8.1</span><br><span class="line"><span class="built_in">sudo</span> apt install python3-venv python3-pip python3-setuptools python3-sphinx ninja-build pkg-config libglib2.0-dev libpixman-1-dev</span><br><span class="line"><span class="comment"># x86_64</span></span><br><span class="line">./configure --target-list=x86_64-softmmu</span><br><span class="line">make -j$(<span class="built_in">nproc</span>)</span><br><span class="line"><span class="built_in">sudo</span> make install</span><br><span class="line"><span class="comment"># aarch64</span></span><br><span class="line">./configure --target-list=aarch64-softmmu</span><br><span class="line">make -j$(<span class="built_in">nproc</span>)</span><br><span class="line"><span class="built_in">sudo</span> make install</span><br></pre></td></tr></table></figure><p>Next, write a script to run with QEMU. Some parameters here are for debugging the program with GDB in the next section, but if you just want to run with QEMU, it won’t affect the operation.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">touch</span> debug.sh</span><br><span class="line"><span class="built_in">chmod</span> a+x debug.sh</span><br></pre></td></tr></table></figure><p><strong>debug-x64.sh</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="built_in">set</span> -e</span><br><span class="line"><span class="built_in">trap</span> <span class="string">&quot;Exiting&quot;</span> INT</span><br><span class="line"></span><br><span class="line"><span class="comment"># environment variables</span></span><br><span class="line"><span class="built_in">source</span> env.sh</span><br><span class="line"></span><br><span class="line"><span class="built_in">export</span> GCC5=/usr/bin/gcc</span><br><span class="line"><span class="comment"># Compiled once, no need to compile again</span></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$EDK_PATH</span></span><br><span class="line"><span class="built_in">source</span> edksetup.sh</span><br><span class="line">build -a X64 -p OvmfPkg/OvmfPkgX64.dsc -t GCC5 -b DEBUG <span class="comment">#-D SOURCE_DEBUG_ENABLE</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$APP_PATH</span></span><br><span class="line"><span class="built_in">mkdir</span> -p _ovmf_dbg</span><br><span class="line"><span class="built_in">cd</span> _ovmf_dbg</span><br><span class="line"><span class="built_in">rm</span> -f debug.log</span><br><span class="line"><span class="comment"># The default QEMU from Ubuntu 22.04 repo is not compatible; we need to upgrade to QEMU v8.1.5</span></span><br><span class="line"><span class="built_in">cp</span> <span class="variable">$EDK_PATH</span>/Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd ./</span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> -p UEFI_Disk</span><br><span class="line"><span class="built_in">cp</span> <span class="variable">$APP_PATH</span>/Build/DEBUG_GCC5/X64/<span class="variable">$INF_BASE_NAME</span>.efi ./UEFI_Disk/</span><br><span class="line"><span class="built_in">cp</span> <span class="variable">$APP_PATH</span>/Build/DEBUG_GCC5/X64/<span class="variable">$INF_BASE_NAME</span>.debug ./UEFI_Disk/</span><br><span class="line"></span><br><span class="line"><span class="comment"># -s enables GDB debugging, default listens at 127.0.0.1:1234</span></span><br><span class="line"><span class="comment"># -bios OVMF.fd, specify OVMF firmware file, this is a QEMU firmware supporting UEFI.</span></span><br><span class="line"><span class="comment"># -debugcon file:debug.log redirects debug output to debug.log file.</span></span><br><span class="line"><span class="comment"># -global isa-debugcon.iobase=0x402 configures the debug console I/O base address.</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">qemu-system-x86_64 \</span><br><span class="line">-s \</span><br><span class="line">-bios OVMF.fd \</span><br><span class="line">-drive format=raw,file=fat:rw:UEFI_Disk/ \</span><br><span class="line">-net none \</span><br><span class="line">-debugcon file:debug.log \</span><br><span class="line">-global isa-debugcon.iobase=0x402 \</span><br><span class="line">-nographic</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>This script first compiles the OVMF (Open Virtual Machine Firmware), which is a firmware based on EDKII that runs on QEMU x86-64 virtual machines. This makes debugging and experimenting with UEFI firmware easier, whether for testing OS booting or using the (built-in) EFI shell.</p><p>The OVMF firmware (for QEMU’s UEFI implementation) is divided into two files:</p><ul><li>OVMF_CODE.fd: contains the actual UEFI firmware.</li><li>OVMF_VARS.fd: acts as a “template” for simulating persistent NVRAM storage.<br>All virtual machine instances can share the read-only OVMF_CODE.fd file from the OVMF package, but each instance needs a private, writable copy of OVMF_VARS.fd.<br>In QEMU, you can specify OVMF_CODE.fd and OVMF_VARS.fd separately, or use a simplified approach:</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Specify separately</span></span><br><span class="line">qemu-system-x86_64 -drive <span class="keyword">if</span>=pflash,format=raw,<span class="built_in">readonly</span>,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF_CODE.fd \</span><br><span class="line">                     -drive <span class="keyword">if</span>=pflash,format=raw,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF_VARS.fd \</span><br><span class="line">                     -nographic \</span><br><span class="line">                     -net none</span><br><span class="line"><span class="comment"># Simplified approach</span></span><br><span class="line">qemu-system-x86_64 -drive <span class="keyword">if</span>=pflash,format=raw,file=Build/OvmfX64/RELEASE_GCC5/FV/OVMF.fd \</span><br><span class="line">                     -nographic \</span><br><span class="line">                     -net none</span><br></pre></td></tr></table></figure><p>Run debug-x64.sh, and you should see the following interface, which is the UEFI Shell:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">UEFI Interactive Shell v2.2</span><br><span class="line">EDK II</span><br><span class="line">UEFI v2.70 (EDK II, 0x00010000)</span><br><span class="line">Mapping table</span><br><span class="line">      FS0: Alias(s):HD0a1:;BLK1:</span><br><span class="line">          PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)</span><br><span class="line">     BLK0: Alias(s):</span><br><span class="line">          PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)</span><br><span class="line">     BLK2: Alias(s):</span><br><span class="line">          PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)</span><br><span class="line">Press ESC <span class="keyword">in</span> 2 seconds to skip startup.nsh or any other key to <span class="built_in">continue</span>.</span><br><span class="line">Shell&gt;</span><br></pre></td></tr></table></figure><p>In this shell, type fs0: (note the English colon), then type HelloWorld.efi to run your program, and the expected output should be “Hello World!!!”</p><div class="tip warning faa-horizontal animated"><p>If the Backspace key doesn’t respond in the shell, try using Ctrl+H instead</p></div><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">UEFI Interactive Shell v2.2</span><br><span class="line">EDK II</span><br><span class="line">UEFI v2.70 (EDK II, 0x00010000)</span><br><span class="line">Mapping table</span><br><span class="line">      FS0: Alias(s):HD0a1:;BLK1:</span><br><span class="line">          PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)/HD(1,MBR,0xBE1AFDFA,0x3F,0xFBFC1)</span><br><span class="line">     BLK0: Alias(s):</span><br><span class="line">          PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)</span><br><span class="line">     BLK2: Alias(s):</span><br><span class="line">          PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0)</span><br><span class="line">Press ESC <span class="keyword">in</span> 2 seconds to skip startup.nsh or any other key to <span class="built_in">continue</span>.</span><br><span class="line">Shell&gt; fs0:</span><br><span class="line">FS0:\&gt; <span class="built_in">ls</span></span><br><span class="line">Directory of: FS0:\</span><br><span class="line">01/08/2025  22:23                  82  gdb_commands.txt</span><br><span class="line">01/10/2025  20:22             184,544  HelloWorld.debug</span><br><span class="line">01/10/2025  20:22               5,760  HelloWorld.efi</span><br><span class="line">01/10/2025  12:22               1,391  NvVars</span><br><span class="line">          4 File(s)     191,777 bytes</span><br><span class="line">          0 Dir(s)</span><br><span class="line">FS0:\&gt; HelloWorld.efi</span><br><span class="line">Hello World!!!</span><br></pre></td></tr></table></figure><p>Exit QEMU by pressing <strong>CTRL+A - X.</strong></p><p>Now, here is the AArch64 version:<br><strong>debug-aarch64.sh</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="built_in">set</span> -e</span><br><span class="line"><span class="built_in">trap</span> <span class="string">&quot;Exiting&quot;</span> INT</span><br><span class="line"></span><br><span class="line"><span class="comment"># Environment variables</span></span><br><span class="line"><span class="built_in">source</span> env.sh</span><br><span class="line"></span><br><span class="line"><span class="built_in">export</span> GCC5_AARCH64_PREFIX=<span class="variable">$UEFI_WORKSPACE</span>/toolchain/gcc-arm-8.2-2019.01-x86_64-aarch64-elf/bin/aarch64-elf-</span><br><span class="line"></span><br><span class="line"><span class="comment"># No need to compile again after one successful compilation</span></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$EDK_PATH</span></span><br><span class="line"><span class="built_in">source</span> edksetup.sh</span><br><span class="line">build -a AARCH64 -p ArmVirtPkg/ArmVirtQemu.dsc -t GCC5 -b RELEASE </span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$APP_PATH</span>/<span class="variable">$INF_NAME</span></span><br><span class="line"><span class="built_in">mkdir</span> -p _armvirt_dbg</span><br><span class="line"><span class="built_in">cd</span> _armvirt_dbg</span><br><span class="line"><span class="built_in">rm</span> -f debug.log</span><br><span class="line"><span class="comment"># Ubuntu 22.04 default QEMU is incompatible, need to upgrade QEMU to version 8.1.5</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cp</span> <span class="variable">$EDK_PATH</span>/Build/ArmVirtQemu-AARCH64/RELEASE_GCC5/FV/QEMU_EFI.fd ./</span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> -p UEFI_Disk</span><br><span class="line"><span class="built_in">cp</span> <span class="variable">$APP_PATH</span>/<span class="variable">$INF_NAME</span>/Build/DEBUG_GCC5/AARCH64/<span class="variable">$INF_BASE_NAME</span>.efi ./UEFI_Disk/</span><br><span class="line"><span class="built_in">cp</span> <span class="variable">$APP_PATH</span>/<span class="variable">$INF_NAME</span>/Build/DEBUG_GCC5/AARCH64/<span class="variable">$INF_BASE_NAME</span>.debug ./UEFI_Disk/</span><br><span class="line"></span><br><span class="line"><span class="comment"># QEMU command</span></span><br><span class="line">qemu-system-aarch64 \</span><br><span class="line">-machine virt,kernel_irqchip=on,gic-version=3 \</span><br><span class="line">-cpu cortex-a57 -m 1G  \</span><br><span class="line">-drive format=raw,file=fat:rw:UEFI_Disk/ \</span><br><span class="line">-bios QEMU_EFI.fd \</span><br><span class="line">-net none \</span><br><span class="line">-nographic</span><br></pre></td></tr></table></figure><h2 id="Debugging"><a href="#Debugging" class="headerlink" title="Debugging"></a>Debugging</h2><p>Debugging UEFI programs using gdb can be a bit tricky, but it can be automated with scripts. The general process is as follows:</p><ol><li>Run debug.sh, then enter UEFI Shell and run the following code (same as using QEMU in the previous section; this is mainly to capture the driver startup address in _ovmf_dbg&#x2F;debug.log).</li><li>Open another terminal and run the script addr.sh below.</li><li>Run gdb -x gdb_commands.txt in the _ovmf_dbg&#x2F;UEFI_Disk directory.</li><li>Set a breakpoint in GDB, e.g., break UefiMain.</li><li>Add the GDB debug target target remote localhost:1234.</li><li>Run and type c to continue to the first breakpoint.</li><li>Run your code in UEFI Shell.</li></ol><p><strong>addr-x64.sh</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="built_in">source</span> env.sh</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> _ovmf_dbg</span><br><span class="line"></span><br><span class="line">logfile=<span class="string">&quot;debug.log&quot;</span></span><br><span class="line"></span><br><span class="line">line=$(grep -oP <span class="string">&quot;Loading driver at 0x[0-9a-fA-F]+ EntryPoint=0x[0-9a-fA-F]+ <span class="variable">$INF_BASE_NAME</span>\.efi&quot;</span> <span class="string">&quot;<span class="variable">$logfile</span>&quot;</span> | <span class="built_in">tail</span> -n 1)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Use regular expression to extract the two addresses</span></span><br><span class="line"><span class="keyword">if</span> [[ <span class="variable">$line</span> =~ Loading\ driver\ at\ (0x[0-9a-fA-F]+)\ EntryPoint=(0x[0-9a-fA-F]+)\ <span class="variable">$INF_BASE_NAME</span>\.efi ]]; <span class="keyword">then</span></span><br><span class="line">    address0=<span class="string">&quot;<span class="variable">$&#123;BASH_REMATCH[1]&#125;</span>&quot;</span></span><br><span class="line">    address1=<span class="string">&quot;<span class="variable">$&#123;BASH_REMATCH[2]&#125;</span>&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;Loading driver at <span class="variable">$address0</span>&quot;</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;EntryPoint=<span class="variable">$address1</span>&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;Error: No matching line found, maybe you need to run <span class="variable">$INF_BASE_NAME</span> in qemu first&quot;</span></span><br><span class="line">    <span class="built_in">exit</span> 0</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> UEFI_Disk</span><br><span class="line"></span><br><span class="line"><span class="comment"># Use objdump to get file header info and extract .text and .data File offsets</span></span><br><span class="line">text_offset=$(objdump -h <span class="string">&quot;<span class="variable">$INF_BASE_NAME</span>.efi&quot;</span> | awk <span class="string">&#x27;</span></span><br><span class="line"><span class="string">  /\.text/ &#123;print $6&#125;  # Extract .text File offset</span></span><br><span class="line"><span class="string">&#x27;</span>)</span><br><span class="line"></span><br><span class="line">data_offset=$(objdump -h <span class="string">&quot;<span class="variable">$INF_BASE_NAME</span>.efi&quot;</span> | awk <span class="string">&#x27;</span></span><br><span class="line"><span class="string">  /\.data/ &#123;print $6&#125;  # Extract .data File offset</span></span><br><span class="line"><span class="string">&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Output extracted results</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;.text file off: <span class="variable">$text_offset</span>&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;.data file off: <span class="variable">$data_offset</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Calculate the addresses</span></span><br><span class="line">text_addr=$((<span class="number">0</span>x<span class="variable">$&#123;address0#0x&#125;</span> + <span class="number">0</span>x<span class="variable">$&#123;text_offset&#125;</span>))</span><br><span class="line">data_addr=$((<span class="number">0</span>x<span class="variable">$&#123;address0#0x&#125;</span> + <span class="number">0</span>x<span class="variable">$&#123;data_offset&#125;</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># Output the results in hexadecimal format</span></span><br><span class="line"><span class="built_in">printf</span> <span class="string">&quot;text_addr: 0x%X   data_addr: 0x%X\n&quot;</span> <span class="variable">$text_addr</span> <span class="variable">$data_addr</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">rm</span> -rf gdb_commands.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># Create gdb_commands.txt and write the contents</span></span><br><span class="line"><span class="built_in">cat</span> &lt;&lt;<span class="string">EOL &gt; gdb_commands.txt</span></span><br><span class="line"><span class="string">file $&#123;INF_BASE_NAME&#125;.efi</span></span><br><span class="line"><span class="string">add-symbol-file $&#123;INF_BASE_NAME&#125;.debug 0x$(printf &quot;%X&quot; $text_addr) -s .data 0x$(printf &quot;%X&quot; $data_addr)</span></span><br><span class="line"><span class="string">EOL</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Output the file content for verification</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;gdb_commands.txt has been created with the following content:&quot;</span></span><br><span class="line"><span class="built_in">printf</span> <span class="string">&quot;\n&quot;</span></span><br><span class="line"><span class="built_in">cat</span> gdb_commands.txt</span><br><span class="line"><span class="built_in">printf</span> <span class="string">&quot;\n&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;Run the following command to debug:&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;cd _ovmf_dbg/UEFI_Disk&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;gdb -x gdb_commands.txt&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;break UefiMain&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;target remote localhost:1234&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;c&quot;</span></span><br></pre></td></tr></table></figure><h1 id="HelloStd"><a href="#HelloStd" class="headerlink" title="HelloStd"></a>HelloStd</h1><p>Another example, using edk-libc to implement a program that calls the standard C library in UEFI.</p><p>You can copy HelloWorld.dsc, modify the GUID, and make sure to change the [<strong>Components</strong>] section to HelloWorld.inf. Finally, add the following line to the [<strong>LibraryClasses</strong>] section at the end:<br><strong>HelloStd.dsc</strong></p><figure class="highlight toml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">!include StdLib/StdLib.inc</span><br></pre></td></tr></table></figure><p>Next, for HelloStd.inf, modify the ENTRY_POINT in the [<strong>Defines</strong>] section to ShellCEntryLib, and in the [<strong>Packages</strong>] section, add the StdLib&#x2F;StdLib.dec and ShellPkg&#x2F;ShellPkg.dec packages. In the [<strong>LibraryClasses</strong>], remove UefiApplicationEntryPoint, and add the LibC and LibStdio libraries. Below is the declaration of HelloStd.inf:</p><p><strong>HelloStd.inf</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Variables defined to be used during the build process</span></span><br><span class="line">[Defines]</span><br><span class="line">  INF_VERSION       = 1.25</span><br><span class="line">  BASE_NAME         = HelloStd</span><br><span class="line">  FILE_GUID         = d0956d2b-c033-45af-8ef2-76c9d30518ec</span><br><span class="line">  MODULE_TYPE       = UEFI_APPLICATION</span><br><span class="line">  VERSION_STRING    = 1.0</span><br><span class="line">  ENTRY_POINT       = ShellCEntryLib</span><br><span class="line"></span><br><span class="line"><span class="comment"># Source code</span></span><br><span class="line">[Sources]</span><br><span class="line">  HelloStd.c</span><br><span class="line"></span><br><span class="line"><span class="comment"># Required packages</span></span><br><span class="line">[Packages]</span><br><span class="line">  MdePkg/MdePkg.dec            <span class="comment"># Contains Uefi and UefiLib</span></span><br><span class="line">  StdLib/StdLib.dec</span><br><span class="line">  ShellPkg/ShellPkg.dec</span><br><span class="line"></span><br><span class="line"><span class="comment"># Required Libraries</span></span><br><span class="line">[LibraryClasses]</span><br><span class="line">  <span class="comment"># UefiApplicationEntryPoint    # Uefi application entry point</span></span><br><span class="line">  UefiLib                      <span class="comment"># UefiLib</span></span><br><span class="line">  LibC</span><br><span class="line">  LibStdio</span><br></pre></td></tr></table></figure><p>Now, we can call standard library programs in UEFI.</p><p><strong>HelloStd.c</strong></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/ShellCEntryLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/UefiBootServicesTableLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/UefiLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Library/UefiRuntimeServicesTableLib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Uefi.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">(IN <span class="type">int</span> Argc, IN <span class="type">char</span> **Argv)</span> &#123;</span><br><span class="line">  EFI_TIME curTime;</span><br><span class="line">  <span class="built_in">printf</span>(<span class="string">&quot;HelloStd!!!\n&quot;</span>);</span><br><span class="line">  gBS-&gt;Stall(<span class="number">2000</span>);</span><br><span class="line">  gRT-&gt;GetTime(&amp;curTime, <span class="literal">NULL</span>);</span><br><span class="line">  <span class="built_in">printf</span>(<span class="string">&quot;Current Time: %d-%d-%d %02d:%02d:%02d\n&quot;</span>, curTime.Year, curTime.Month,</span><br><span class="line">         curTime.Day, curTime.Hour, curTime.Minute, curTime.Second);</span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Finally, modify PROJ_NAME, DSC_NAME, INF_NAME, and INF_BASE_NAME in env.sh, and you can compile and debug as described in the HelloWorld section.</p><h1 id="References"><a href="#References" class="headerlink" title="References"></a>References</h1><div class="reference-source"><span class="hidden-anchor" id="referfrom_[1]"></span><a class="reference-anchor" href="#referto_[1]">[1]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://github.com/Kostr/UEFI-Lessons">UEFI-Lessons</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[2]"></span><a class="reference-anchor" href="#referto_[2]">[2]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://github.com/luobing/uefi-practical-programming">UEFI Programming Practice by Luo Bing</a></div>]]></content>
    
    
    <summary type="html">Setting up a UEFI development environment in Linux with compilation and debugging scripts, supporting x64 and aarch64 architectures.</summary>
    
    
    
    <category term="UEFI" scheme="https://even629.com/en/categories/UEFI/"/>
    
    
    <category term="UEFI" scheme="https://even629.com/en/tags/UEFI/"/>
    
  </entry>
  
  <entry>
    <title>Emacs</title>
    <link href="https://even629.com/en/posts/28520/"/>
    <id>https://even629.com/en/posts/28520/</id>
    <published>2025-01-09T08:18:13.000Z</published>
    <updated>2025-01-09T08:18:13.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Commonly-used-selection-commands"><a href="#Commonly-used-selection-commands" class="headerlink" title="Commonly used selection commands"></a>Commonly used selection commands</h2><table><thead><tr><th>Command</th><th>Name</th><th>Effect</th></tr></thead><tbody><tr><td>M - h</td><td>mark-paragraph</td><td>Select a paragraph</td></tr><tr><td>C - x + C - p</td><td>mark-page</td><td>Select the entire page</td></tr><tr><td>C - x h</td><td>mark-whole-buffer</td><td>Select the entire content of the editing window</td></tr><tr><td>M - y</td><td>yank-pop</td><td>After C - y, paste previous items in the clipboard</td></tr></tbody></table><h1 id="Location-of-Emacs-configuration-files-on-Windows"><a href="#Location-of-Emacs-configuration-files-on-Windows" class="headerlink" title="Location of Emacs configuration files on Windows"></a>Location of Emacs configuration files on Windows</h1><p>On Windows, the .emacs file may be called _emacs for backward compatibility with DOS and FAT filesystems where filenames could not start with a dot. Some users prefer to continue using such a name because Explorer cannot create a file with a name starting with a dot, even though the filesystem and most other programs can handle it. In Emacs 22 and later, the init file may also be called .emacs.d&#x2F;init.el. Many of the other files created by Lisp packages are now stored in the .emacs.d directory too, so this keeps all your Emacs-related files in one place.</p><p>All the files mentioned above should go in your HOME directory. The HOME directory is determined by following the steps below:</p><ol><li>If the environment variable HOME is set, use the directory it indicates.</li><li>If the registry entry HKCU\SOFTWARE\GNU\Emacs\HOME is set, use the directory it indicates.</li><li>If the registry entry HKLM\SOFTWARE\GNU\Emacs\HOME is set, use the directory it indicates. Not recommended, as it results in users sharing the same HOME directory.</li><li>If C:.emacs exists, then use C:. This is for backward compatibility, as previous versions defaulted to C:\ if HOME was not set.</li><li>Use the user’s AppData directory, usually a directory called Application Data under the user’s profile directory, the location of which varies according to Windows version and whether the computer is part of a domain.</li></ol><p>That is to say, there are three formats for Emacs configuration files: the .emacs file, the _emacs file, or the init.el file in the .emacs.d directory (for version 22 or higher). However, no matter which format is used, Emacs can only find the configuration file if it is placed in the correct directory, which is the HOME directory.</p><p>Friends familiar with Linux generally know the home directory, which is simply represented by ~ or the full path &#x2F;home&#x2F;<xxx>, where xxx represents the user name. So, on Linux, just place .emacs and .emacs.d in this directory. However, Windows does not have the concept of a home directory, so Emacs searches for configuration files as follows:</p><ol><li>If the HOME environment variable is set, use its value as the home directory ~.</li><li>If the registry key HKCU\SOFTWARE\GNU\Emacs\HOME exists, use its value as the home directory ~.</li><li>If the registry key HKLM\SOFTWARE\GNU\Emacs\HOME exists, use its value as the home directory ~ (the difference from 2 is that 2 is only for the current user’s registry path, while 3 is for all users).</li><li>If C:.emacs exists, use C:\ as the home directory ~.</li><li>If none of the above exist, use <system root>\Users<user name>\AppData\Roaming as the home directory ~ (for XP and earlier Windows users, you need to look in the Documents and Settings directory).</li></ol><p><strong>From the above strategies, method 1 is a better practice, so it has the highest priority and should be the recommended way. Therefore, create a new HOME environment variable and set its value to the place where you want to place the Emacs configuration files.</strong></p><p><strong>Previously, I set the HOME directory as described above, but now I regret it because I found that not only Emacs uses the HOME environment variable. At least the following programs or plugins also use this variable:</strong></p><ol><li><strong>VIM, which places the _viminfo file in this directory.</strong></li><li><strong>The neocomplcache plugin for VIM, which places a .neocon directory in it.</strong></li><li><strong>The pentadactyl plugin for Firefox, which places a pentadactyl directory in it.</strong></li></ol><p><strong>Therefore, personal suggestions are as follows:</strong></p><ol><li><strong>If you want a common directory to store these configurations, just like the ~ directory on Linux, then setting the HOME environment variable is the most suitable option.</strong></li><li><strong>If you want this directory to store only Emacs configurations, then don’t use the HOME environment variable. Instead, add a HOME key value in the registry. (Personally, I prefer this method.)</strong></li></ol><p>That is:</p><p>Create a GNU item under HKEY_LOCAL_MACHINE\SOFTWARE, create an Emacs item under the GNU item, and then create a string value in Emacs with the key HOME and the value set to the path where you want to store the files.</p><h1 id="Emacs-tutorials"><a href="#Emacs-tutorials" class="headerlink" title="Emacs tutorials"></a>Emacs tutorials</h1><p>C: Ctrl<br>M: Alt</p><h2 id="Exit-Emacs"><a href="#Exit-Emacs" class="headerlink" title="Exit Emacs"></a>Exit Emacs</h2><p><strong>C-x C-c</strong></p><h2 id="Exit-a-running-command"><a href="#Exit-a-running-command" class="headerlink" title="Exit a running command"></a>Exit a running command</h2><p><strong>C-g</strong></p><h2 id="Move-to-the-next-screen"><a href="#Move-to-the-next-screen" class="headerlink" title="Move to the next screen"></a>Move to the next screen</h2><p><strong>C-v</strong></p><h2 id="Move-to-the-previous-screen"><a href="#Move-to-the-previous-screen" class="headerlink" title="Move to the previous screen"></a>Move to the previous screen</h2><p><strong>M-v</strong></p><h2 id="Redraw-the-screen-and-center-the-line-where-the-cursor-is-located-on-the-screen"><a href="#Redraw-the-screen-and-center-the-line-where-the-cursor-is-located-on-the-screen" class="headerlink" title="Redraw the screen and center the line where the cursor is located on the screen"></a>Redraw the screen and center the line where the cursor is located on the screen</h2><p><strong>C-l (here it is CTRL-L)</strong></p><h2 id="Basic-cursor-control"><a href="#Basic-cursor-control" class="headerlink" title="Basic cursor control"></a>Basic cursor control</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">                Previous line C-p</span><br><span class="line">                      :</span><br><span class="line">                      :</span><br><span class="line">Move left C-b .... Current cursor position .... Move right C-f</span><br><span class="line">                      :</span><br><span class="line">                      :</span><br><span class="line">                 Next line C-n</span><br></pre></td></tr></table></figure><p>Each line of text ends with a “newline character”, which distinguishes one line from another. (Normally, the last line of a file has a newline character, but Emacs does not enforce this.)</p><h3 id="Move-to-the-previous-line"><a href="#Move-to-the-previous-line" class="headerlink" title="Move to the previous line"></a>Move to the previous line</h3><p><strong>Ctrl + p</strong></p><p>Previous</p><h3 id="Move-to-the-next-line"><a href="#Move-to-the-next-line" class="headerlink" title="Move to the next line"></a>Move to the next line</h3><p><strong>Ctrl + n</strong></p><p>Next</p><h3 id="Move-one-character-to-the-left"><a href="#Move-one-character-to-the-left" class="headerlink" title="Move one character to the left"></a>Move one character to the left</h3><p><strong>Ctrl + b</strong></p><p>Backward</p><h3 id="Move-one-character-to-the-right"><a href="#Move-one-character-to-the-right" class="headerlink" title="Move one character to the right"></a>Move one character to the right</h3><p><strong>Ctrl + f</strong></p><p>Forward</p><h3 id="Move-the-cursor-forward-one-word"><a href="#Move-the-cursor-forward-one-word" class="headerlink" title="Move the cursor forward one word"></a>Move the cursor forward one word</h3><p>Here, a word refers to an English word in English text and means moving to the next punctuation mark in Chinese text.</p><p><strong>Alt + f</strong></p><h3 id="Move-the-cursor-backward-one-word"><a href="#Move-the-cursor-backward-one-word" class="headerlink" title="Move the cursor backward one word"></a>Move the cursor backward one word</h3><p><strong>Alt + b</strong></p><h3 id="Move-the-cursor-to-the-beginning-of-the-line"><a href="#Move-the-cursor-to-the-beginning-of-the-line" class="headerlink" title="Move the cursor to the beginning of the line"></a>Move the cursor to the beginning of the line</h3><p><strong>Ctrl + a</strong></p><p>Beginning of the line</p><h3 id="Move-the-cursor-to-the-end-of-the-line"><a href="#Move-the-cursor-to-the-end-of-the-line" class="headerlink" title="Move the cursor to the end of the line"></a>Move the cursor to the end of the line</h3><p><strong>Ctrl + e</strong></p><p>End of the line</p><h3 id="Move-the-cursor-to-the-beginning-of-a-sentence"><a href="#Move-the-cursor-to-the-beginning-of-a-sentence" class="headerlink" title="Move the cursor to the beginning of a sentence"></a>Move the cursor to the beginning of a sentence</h3><p><strong>Alt + a</strong></p><h3 id="Move-the-cursor-to-the-end-of-a-sentence"><a href="#Move-the-cursor-to-the-end-of-a-sentence" class="headerlink" title="Move the cursor to the end of a sentence"></a>Move the cursor to the end of a sentence</h3><p><strong>Alt + e</strong></p><h3 id="Move-the-cursor-to-the-very-beginning-of-all-the-text"><a href="#Move-the-cursor-to-the-very-beginning-of-all-the-text" class="headerlink" title="Move the cursor to the very beginning of all the text"></a>Move the cursor to the very beginning of all the text</h3><p><strong>Alt + Shift + ,</strong></p><h3 id="Move-the-cursor-to-the-very-end-of-all-the-text"><a href="#Move-the-cursor-to-the-very-end-of-all-the-text" class="headerlink" title="Move the cursor to the very end of all the text"></a>Move the cursor to the very end of all the text</h3><p><strong>Alt + Shift + .</strong></p><h3 id="Select-multiple-characters-with-the-cursor"><a href="#Select-multiple-characters-with-the-cursor" class="headerlink" title="Select multiple characters with the cursor"></a>Select multiple characters with the cursor</h3><p><strong>Ctrl + Shift + r Ctrl + Shift + f</strong></p><h2 id="Move-line-blocks"><a href="#Move-line-blocks" class="headerlink" title="Move line blocks"></a>Move line blocks</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">(use-package drag-stuff</span><br><span class="line">             :bind ((&quot;&lt;M-up&gt;&quot; . drag-stuff-up)</span><br><span class="line">                    (&quot;&lt;M-down&gt;&quot; . drag-stuff-down)))</span><br></pre></td></tr></table></figure><p><strong>M - Up Arrow</strong></p><h2 id="Swap-Order"><a href="#Swap-Order" class="headerlink" title="Swap Order"></a>Swap Order</h2><h3 id="Swap-two-characters-before-and-after-the-cursor"><a href="#Swap-two-characters-before-and-after-the-cursor" class="headerlink" title="Swap two characters before and after the cursor"></a>Swap two characters before and after the cursor</h3><p><strong>C - t</strong></p><h3 id="Swap-two-words-before-and-after-the-cursor"><a href="#Swap-two-words-before-and-after-the-cursor" class="headerlink" title="Swap two words before and after the cursor"></a>Swap two words before and after the cursor</h3><p><strong>M - t</strong></p><h2 id="Copy"><a href="#Copy" class="headerlink" title="Copy"></a>Copy</h2><p><strong>M - w</strong></p><h2 id="Cut"><a href="#Cut" class="headerlink" title="Cut"></a>Cut</h2><p><strong>C - w</strong></p><h2 id="Paste"><a href="#Paste" class="headerlink" title="Paste"></a>Paste</h2><p><strong>C - y</strong></p><p>yank</p><h2 id="Parameter-Control"><a href="#Parameter-Control" class="headerlink" title="Parameter Control"></a>Parameter Control</h2><p>Most Emacs commands accept numerical parameters. For most commands, these numerical parameters are used to <strong>specify the number of times the command should be repeated</strong>.</p><p><strong>First, enter C - u, then enter a number as a parameter, and finally enter the command.</strong></p><p>For example: C - u 8 C - f will move the cursor forward by 8 characters.</p><p>Some Emacs commands use numerical parameters for other purposes.</p><p>For example: C - v and M - v.<br>When given a parameter, they will scroll by the specified number of lines instead of screens.<br>That is, C - u 8 C - v will move the cursor down by 8 lines.</p><h2 id="Panes"><a href="#Panes" class="headerlink" title="Panes"></a>Panes</h2><h3 id="Close-redundant-panes"><a href="#Close-redundant-panes" class="headerlink" title="Close redundant panes"></a>Close redundant panes</h3><p><strong>C - x 1</strong><br>Keep only one pane, which means closing all other panes, expanding the remaining pane to the entire screen, and closing all other panes at the same time.</p><p>There is a series of commands starting with CONTROL - x. Many of these commands are related to panes, files, buffers, etc.</p><h2 id="Insertion"><a href="#Insertion" class="headerlink" title="Insertion"></a>Insertion</h2><h3 id="Insert-multiple-identical-characters"><a href="#Insert-multiple-identical-characters" class="headerlink" title="Insert multiple identical characters"></a>Insert multiple identical characters</h3><p><strong>C - u 8</strong> *****<br>This will insert *********.</p><h2 id="Deletion"><a href="#Deletion" class="headerlink" title="Deletion"></a>Deletion</h2><h3 id="Delete-the-character-after-the-cursor"><a href="#Delete-the-character-after-the-cursor" class="headerlink" title="Delete the character after the cursor"></a>Delete the character after the cursor</h3><p><strong>C - d</strong><br>delete<br>Equivalent to the delete key on the keyboard.</p><h3 id="Delete-the-word-after-the-cursor"><a href="#Delete-the-word-after-the-cursor" class="headerlink" title="Delete the word after the cursor"></a>Delete the word after the cursor</h3><p><strong>M - d</strong></p><h3 id="Delete-the-characters-from-the-cursor-to-the-end-of-the-line"><a href="#Delete-the-characters-from-the-cursor-to-the-end-of-the-line" class="headerlink" title="Delete the characters from the cursor to the end of the line"></a>Delete the characters from the cursor to the end of the line</h3><p><strong>C - k</strong><br>kill</p><h3 id="Delete-the-characters-from-the-cursor-to-the-end-of-the-sentence"><a href="#Delete-the-characters-from-the-cursor-to-the-end-of-the-sentence" class="headerlink" title="Delete the characters from the cursor to the end of the sentence"></a>Delete the characters from the cursor to the end of the sentence</h3><p><strong>M - k</strong></p><p>Note that the difference between “kill” and “delete” is that the killed text can be re - inserted (anywhere), while the deleted text cannot be re - inserted in the same way (although you can undo a delete command, which will be mentioned later). [In fact, although the killed text seems to “disappear”, it is actually recorded by Emacs and can be retrieved; while the deleted text may still be in memory, but it has been “discarded” by Emacs and cannot be retrieved.] Re - inserting the killed text is called “yanking”. Generally, commands that may delete a large amount of text will record the deleted text (they are set to be “yankable”), while commands that only delete one character or only delete whitespace will not record the deleted content (naturally, you cannot yank it).</p><p>Note that a single C - k will remove the content of a line, and the second C - k will remove the newline character and move all subsequent lines up. The way C - k handles numerical parameters is very special. It will remove the specified number of lines along with their newline characters, rather than simply repeating C - k. For example, C - u 2C - k will remove two lines and their newline characters; obviously, just entering C - k twice will not achieve this result.</p><h2 id="Yank-Paste"><a href="#Yank-Paste" class="headerlink" title="Yank (Paste)"></a>Yank (Paste)</h2><p>The action of re - inserting the removed text is called “yanking”. (It’s like pulling back something that was taken away from you forcefully.) You can yank at the place where you deleted the text, or at other places, and you can also yank the same text multiple times to get multiple copies. Many other editors call “kill” and “yank” “cut” and “paste”.</p><h3 id="Yank-the-most-recently-removed-content"><a href="#Yank-the-most-recently-removed-content" class="headerlink" title="Yank the most recently removed content"></a>Yank the most recently removed content</h3><p><strong>C - y</strong><br>yanking</p><h3 id="Yank-the-previously-removed-content"><a href="#Yank-the-previously-removed-content" class="headerlink" title="Yank the previously removed content"></a>Yank the previously removed content</h3><p><strong>M - y</strong><br>You need to press C - y first and then M - y.</p><h2 id="Undo"><a href="#Undo" class="headerlink" title="Undo"></a>Undo</h2><p><strong>C - &#x2F;</strong><br>Or <strong>C - _</strong> or <strong>C - x u</strong></p><h2 id="Search"><a href="#Search" class="headerlink" title="Search"></a>Search</h2><p>Emacs can search for strings (a “string” refers to a sequence of consecutive characters) forward or backward.</p><p>The search command is a <strong>command to move the cursor</strong>: after a successful search, the cursor will stay at the position where the search target appears.</p><h3 id="Search-forward"><a href="#Search-forward" class="headerlink" title="Search forward"></a>Search forward</h3><p><strong>C - s</strong><br>During an incremental search, Emacs will try to jump to the position where the search target appears. To jump to the next match, press C - s again. If the target cannot be found, Emacs will beep to tell you that the search has failed. Throughout the process, you can use C - g to terminate the search. [You will find that C - g will move the cursor back to the starting position of the search, while <Return> will leave the cursor at the search result, which is a very useful feature.]</p><h3 id="Search-backward"><a href="#Search-backward" class="headerlink" title="Search backward"></a>Search backward</h3><p><strong>C - r</strong></p><h2 id="Replace"><a href="#Replace" class="headerlink" title="Replace"></a>Replace</h2><p><strong>M - %</strong><br>When replacing, press y to confirm the replacement, n to skip the current replacement, and! to replace all.</p><h2 id="Files"><a href="#Files" class="headerlink" title="Files"></a>Files</h2><h3 id="Find-a-file"><a href="#Find-a-file" class="headerlink" title="Find a file"></a>Find a file</h3><p><strong>C - x C - f</strong></p><h3 id="Save-a-file"><a href="#Save-a-file" class="headerlink" title="Save a file"></a>Save a file</h3><p><strong>C - x C - s</strong><br>This command saves the text in Emacs to a file. When saving a file for the first time, Emacs will rename the original file for backup. The renaming rule is usually to add a “~” character after the original file name. You can turn off this feature.</p><h2 id="Buffers"><a href="#Buffers" class="headerlink" title="Buffers"></a>Buffers</h2><p>Emacs stores each file being edited in a place called a “buffer”. Every time you find a file, Emacs creates a buffer inside. You can list all the current buffers with the following command:</p><p>   C - x C - b  List buffers</p><p>Enter C - x 1 to leave the buffer list.</p><p>Regardless of how many buffers there are, there can only be one “current” buffer at any time, which is the one you are currently editing. If you want to edit another buffer, you must “switch” to it. As mentioned above, using C - x C - f is one way. However, there is a simpler way, which is to use C - x b. With this command, you must enter the name of the buffer.</p><p>In most cases, the buffer has the same name as its corresponding file (excluding the directory name), but this is not absolute. The buffer list obtained by C - x C - b always shows the buffer names.</p><p>A buffer does not necessarily have a corresponding file. The buffer that displays the buffer list (called “<em>Buffer List</em>“) is such an example. The TUTORIAL.cn buffer initially did not have a corresponding file, but now it does because in the previous section you entered C - x C - s to save it as a file.</p><p>The “<em>Messages</em>“ buffer also does not have a corresponding file. This buffer stores all the messages that appear at the bottom of Emacs.</p><p>If you make some changes to a file and then switch to another file, this action will not save the previous file for you. The changes to the first file still only exist in Emacs, that is, in its corresponding buffer. Moreover, the changes to the second file will not affect the first file. This is very useful, but it also means that you need a convenient way to save the buffer of the first file. Switching back to that buffer and then using C - x C - s to save it is too troublesome. You need a simpler method, and Emacs has already prepared one for you:</p><p>   C - x s  Save multiple buffers</p><p>C - x s will find all the buffers that have been modified but not saved, and then ask you one by one: Do you want to save them?</p><h2 id="Command-Set-Extension"><a href="#Command-Set-Extension" class="headerlink" title="Command Set Extension"></a>Command Set Extension</h2><p>The number of Emacs commands is as countless as the stars in the sky. It is obviously impossible to map them all to the CONTROL and META key combinations. Emacs uses extension (eXtend) commands to solve this problem. There are two styles of extension commands:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">C - x     Character extension. Enter another character or key combination after C - x.</span><br><span class="line">    M - x     Command name extension. Enter a command name after M - x.</span><br></pre></td></tr></table></figure><h3 id="Line-Sorting"><a href="#Line-Sorting" class="headerlink" title="Line Sorting"></a>Line Sorting</h3><p><strong>M-x sort-lines</strong></p><h3 id="Word-Counting"><a href="#Word-Counting" class="headerlink" title="Word Counting"></a>Word Counting</h3><p>Count the entire buffer</p><p><strong>M-x count-words-region</strong></p><p>Count the selected region</p><p><strong>M-x count-words</strong></p><h2 id="Automatic-Saving"><a href="#Automatic-Saving" class="headerlink" title="Automatic Saving"></a>Automatic Saving</h2><p>If you have modified a file but your computer crashes before you can save it, the changes you made are likely to be lost. To avoid such an unfortunate situation, Emacs periodically writes the file you are editing into an “automatic save” file. The file name of the automatic save file has a “#” character at both the beginning and the end. For example, if the file you are editing is called “hello.c”, then its automatic save file is called “#hello.c#”. This file will be deleted by Emacs after a regular save.</p><p>So, if such an unfortunate event does occur, you can calmly open the original file (note that it’s not the automatic save file) and then enter <code>M-x recover-file &lt;Return&gt;</code> to restore your automatic save file. When prompted for confirmation, enter <code>yes &lt;Return&gt;</code>.</p><h2 id="Status-Bar"><a href="#Status-Bar" class="headerlink" title="Status Bar"></a>Status Bar</h2><p>The line directly above the echo area is called the “status bar”. The status bar displays some information, such as:</p><p>-:**- TUTORIAL.cn 63% L749 (Fundamental)</p><ul><li>The status bar shows the status of Emacs and some information about the text you are editing.</li><li>You should know what the file name means, right? It’s the file you found.</li><li>-NN%– indicates the position of the cursor in the entire text. If it’s at the beginning of the file, it shows –Top– instead of –00%–; if it’s at the end of the file, it shows –Bot–. If the file is small enough to be displayed entirely on one screen, the status bar will show –All–.</li><li>The “L” followed by a number gives the line number where the cursor is located.</li><li>The asterisk (*) at the very beginning indicates that you have made changes to the text. A newly opened file definitely hasn’t been modified, so the status bar shows a dash (-) instead of an asterisk.</li><li>The content in the parentheses on the status bar tells you the current editing mode. The default mode is Fundamental, which is the one you are currently using. It is a “major mode”.</li></ul><h2 id="Modes"><a href="#Modes" class="headerlink" title="Modes"></a>Modes</h2><p>Major modes are all extended commands that can be launched with M-x. You can switch to the Fundamental mode by using <code>M-x fundamental-mode</code>.</p><p><code>M-x text-mode &lt;Return&gt;</code>: Switch to text mode.</p><p>You can view the documentation of the current major mode by using <code>C-h m</code>. Enter <code>C-x 1</code> to close the documentation pane.</p><ul><li>Major modes are called “major” because there are also “minor modes” at the same time. Minor modes cannot replace major modes but provide some auxiliary functions. Each minor mode can be independently enabled and disabled, regardless of other minor modes and the major mode. So you can choose not to use minor modes, or use only one or multiple minor modes simultaneously.</li><li>A minor mode called “Auto Fill” is very useful, especially when editing natural language text. After enabling Auto Fill, Emacs will automatically insert a line break when you type beyond the line boundary.</li><li>Use <code>M-x auto-fill-mode &lt;Return&gt;</code> to start the Auto Fill mode. Using this command again will turn off the Auto Fill mode. That is to say, if the Auto Fill mode is not enabled, this command will enable it; if it is already enabled, this command will disable it. Therefore, we say that this command can be used to “toggle” the mode.</li><li>The line boundary is usually set to 70 characters (here referring to English characters). You can use the <code>C-x f</code> command with a numeric parameter to reset it.</li><li>If you make some changes in the middle of a paragraph, the Auto Fill mode will not re-wrap the entire paragraph for you. You need to manually re-wrap it using <code>M-q</code>. Note that the cursor must be within the paragraph you want to re-wrap.</li></ul><h2 id="Window-Management"><a href="#Window-Management" class="headerlink" title="Window Management"></a>Window Management</h2><p>Switch buffers</p><p>C-x b</p><p>Kill the current buffer</p><p>C-x k</p><p>Manage buffers in bulk</p><p>C-x C-b ;; Enter the buffer list</p><ul><li>d ;; Mark for deletion</li><li>u ;; Unmark the current line</li><li>U ;; Unmark all lines</li><li>x ;; Execute the operation</li><li>? ;; View key help</li></ul><h2 id="Multiple-Panes-Split-Screen"><a href="#Multiple-Panes-Split-Screen" class="headerlink" title="Multiple Panes (Split Screen)"></a>Multiple Panes (Split Screen)</h2><h3 id="Divide-the-screen-into-two-panes"><a href="#Divide-the-screen-into-two-panes" class="headerlink" title="Divide the screen into two panes"></a>Divide the screen into two panes</h3><p><strong>C-x 0</strong></p><p>Close the current split screen</p><p><strong>C-x 1</strong></p><p>Keep only the current split screen</p><p><strong>C-x 2</strong></p><p>Split the screen vertically</p><p><strong>C-x 3</strong></p><p>Split the screen horizontally</p><h3 id="Adjust-the-width-of-split-screens"><a href="#Adjust-the-width-of-split-screens" class="headerlink" title="Adjust the width of split screens"></a>Adjust the width of split screens</h3><p>Increase the height: C-x ^</p><p>Increase&#x2F;decrease the width: C-x {C-x }</p><h3 id="Move-the-cursor-to-another-pane"><a href="#Move-the-cursor-to-another-pane" class="headerlink" title="Move the cursor to another pane"></a>Move the cursor to another pane</h3><p><strong>C-x o</strong></p><p>Here, “o” means “other”.</p><p>When you are editing in one pane and using another pane as a reference, the <code>C-M-v</code> command is very useful. You can use the <code>C-M-v</code> command to scroll the text in another pane without leaving the selected pane. [For example, translation and proofreading are very suitable to be done in this way.]</p><p>(In the upper pane) Enter <code>C-x 1</code> to close the lower pane.</p><p>When there are many split screens, the efficiency is very low. You can use the <code>ace-window</code> plugin to quickly jump between windows. There are many similar plugins, but this one is the best solution.</p><p><strong>M-o</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">(use-package ace-window </span><br><span class="line">             :bind ((&quot;M-o&quot; . &#x27;ace-window)))</span><br></pre></td></tr></table></figure><p><img src="https://cdn.jsdelivr.net/gh/even629/myPicGo/1673110725303-6cb4c6aa-b022-46d2-827b-1b7befb54e8b.png" alt="ace-window" loading="lazy"></p><h3 id="Open-a-file-in-a-new-pane"><a href="#Open-a-file-in-a-new-pane" class="headerlink" title="Open a file in a new pane"></a>Open a file in a new pane</h3><p><strong>C-x 4 C-f</strong></p><h2 id="Multiple-windows"><a href="#Multiple-windows" class="headerlink" title="Multiple windows"></a>Multiple windows</h2><h3 id="Create-a-new-window"><a href="#Create-a-new-window" class="headerlink" title="Create a new window"></a>Create a new window</h3><p><strong>M-x make-frame</strong></p><h3 id="Close-the-selected-window"><a href="#Close-the-selected-window" class="headerlink" title="Close the selected window"></a>Close the selected window</h3><p><strong>M-x delete-frame</strong></p><h2 id="Get-more-help"><a href="#Get-more-help" class="headerlink" title="Get more help"></a>Get more help</h2><p>Emacs provides some commands to view the documentation of Emacs commands. These commands all start with CONTROL-h, and this character is therefore called the “Help character”.</p><p>The most basic help function is C-h c. After entering C-h c and then a key combination, Emacs will give a brief description of this command.</p><p>Enter C-h c C-p.</p><p>The displayed message should be like this:</p><pre><code>C-p runs the command previous-line</code></pre><p>This message shows the function name corresponding to the C-p command. The function of a command is implemented by a function, so the function name itself can also be regarded as the simplest documentation - at least for the commands you have learned, their function names are sufficient to explain their functions.</p><p>If you want more information, try replacing C-h c with C-h k.</p><p>Enter C-h k C-p.</p><p>The above command will open a new Emacs pane to display the function name and its documentation. After you finish reading, you can use C-x 1 to close this help pane. Of course, you don’t need to do this immediately. You can first do something else in the editing pane and then close the help pane.</p><p>C-h f explains a function. You need to enter the function name.</p><p>Enter C-h f previous-line <Return>. Emacs will give all the information it knows about “the function that implements the C-p command”.</p><p>C-h v is used to display the documentation of Emacs variables. Emacs variables can be used to “customize the behavior of Emacs”. Similarly, you need to enter the name of the variable.</p><p>C-h a is for Command Apropos. Enter a keyword and Emacs will list all commands whose names contain this keyword. All these commands can be launched with M-x. For some commands, the Command Apropos will also list one or two key combinations.</p><p>Enter C-h a file <Return>.</p><p>Emacs will display a list of M-x commands in another pane. This list contains all commands whose names contain “file”. You can see key combinations like “C-x C-f” displayed next to command names like “find-file”.</p><p>C-h i is for reading the manual (usually referred to as Info). This command will open a special buffer called “<em>info</em>“, where you can read the usage manuals of the software packages installed in the system. To read the Emacs usage manual, press m emacs <Return>. If you have never used the Info system before, press “?” and Emacs will guide you through the Info usage guide. After reading this quick guide, Emacs Info will become your main reference document.</p>]]></content>
    
    
    <summary type="html">Some basic operations of Emacs</summary>
    
    
    
    <category term="emacs" scheme="https://even629.com/en/categories/emacs/"/>
    
    
    <category term="emacs" scheme="https://even629.com/en/tags/emacs/"/>
    
  </entry>
  
</feed>
