mirror of
https://github.com/timmypidashev/web.git
synced 2026-04-14 19:13:51 +00:00
Compare commits
6 Commits
87d3b3bfa6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
222e01d18e
|
|||
|
384ae63300
|
|||
|
eac8018a83
|
|||
|
de546d6ff0
|
|||
|
9965bd3529
|
|||
|
f0ae0b9ce1
|
@@ -1,3 +1 @@
|
|||||||
|
|
||||||

|
|
||||||
<img src=".github/preview.jpeg" title="Preview"/>
|
<img src=".github/preview.jpeg" title="Preview"/>
|
||||||
|
|||||||
BIN
public/blog/thinkpad-t440p-coreboot-guide/eeprom_chip_4mb.webp
Normal file
BIN
public/blog/thinkpad-t440p-coreboot-guide/eeprom_chip_4mb.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
BIN
public/blog/thinkpad-t440p-coreboot-guide/eeprom_chip_8mb.webp
Normal file
BIN
public/blog/thinkpad-t440p-coreboot-guide/eeprom_chip_8mb.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 742 KiB |
Submodule public/scripts updated: cf15115731...a238334ae5
@@ -439,8 +439,15 @@ function GlitchCountdown({ seconds }: { seconds: number }) {
|
|||||||
|
|
||||||
export default function Hero() {
|
export default function Hero() {
|
||||||
const [phase, setPhase] = useState<
|
const [phase, setPhase] = useState<
|
||||||
"intro" | "full" | "retired" | "countdown" | "glitch"
|
"intro" | "full" | "retired" | "countdown" | "glitch" | "void"
|
||||||
>("intro");
|
>(() => {
|
||||||
|
if (import.meta.env.DEV && typeof window !== "undefined") {
|
||||||
|
const p = new URLSearchParams(window.location.search);
|
||||||
|
if (p.has("debug-glitch")) return "glitch";
|
||||||
|
if (p.has("debug-countdown")) return "countdown";
|
||||||
|
}
|
||||||
|
return "intro";
|
||||||
|
});
|
||||||
const [fading, setFading] = useState(false);
|
const [fading, setFading] = useState(false);
|
||||||
const [cycle, setCycle] = useState(0);
|
const [cycle, setCycle] = useState(0);
|
||||||
const [countdown, setCountdown] = useState(150);
|
const [countdown, setCountdown] = useState(150);
|
||||||
@@ -482,49 +489,81 @@ export default function Hero() {
|
|||||||
}, [phase]);
|
}, [phase]);
|
||||||
|
|
||||||
// Glitch → transition into void
|
// Glitch → transition into void
|
||||||
const glitchRef = useRef<HTMLDivElement>(null);
|
// Apply animation directly to each visible element (works on both desktop + mobile)
|
||||||
|
// On mobile, filter/transform on <body> doesn't reach fixed-position children,
|
||||||
|
// so we target the elements themselves
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (phase !== "glitch") return;
|
if (phase !== "glitch") return;
|
||||||
|
|
||||||
// Apply glitch to all direct children of the layout wrapper
|
|
||||||
const wrapper = glitchRef.current?.closest("main")?.parentElement || document.body;
|
|
||||||
const style = document.createElement("style");
|
const style = document.createElement("style");
|
||||||
style.textContent = `
|
style.textContent = `
|
||||||
.hero-glitch-child {
|
.hero-glitch-shake {
|
||||||
animation: hero-glitch 3s ease-in forwards;
|
animation: hero-glitch-shake 3s ease-in forwards !important;
|
||||||
}
|
}
|
||||||
@keyframes hero-glitch {
|
@keyframes hero-glitch-shake {
|
||||||
0% { filter: none; transform: none; opacity: 1; }
|
0% { transform: none; }
|
||||||
5% { filter: hue-rotate(90deg) saturate(3); transform: skewX(2deg); }
|
5% { transform: skewX(2deg); }
|
||||||
10% { filter: invert(1); transform: skewX(-3deg) translateX(5px); }
|
10% { transform: skewX(-3deg) translateX(5px); }
|
||||||
15% { filter: hue-rotate(180deg) brightness(1.5); transform: scale(1.02); }
|
15% { transform: scale(1.02); }
|
||||||
20% { filter: saturate(5) contrast(2); transform: skewX(1deg) translateY(-2px); }
|
20% { transform: skewX(1deg) translateY(-2px); }
|
||||||
25% { filter: invert(1) hue-rotate(270deg); transform: skewX(-2deg); }
|
25% { transform: skewX(-2deg); }
|
||||||
30% { filter: brightness(2) saturate(0); transform: scale(0.98); }
|
30% { transform: scale(0.98); }
|
||||||
40% { filter: hue-rotate(45deg) contrast(3); transform: translateX(-3px); }
|
40% { transform: translateX(-3px); }
|
||||||
50% { filter: invert(1) brightness(0.5); transform: skewX(4deg) skewY(1deg); }
|
50% { transform: skewX(4deg) skewY(1deg); }
|
||||||
60% { filter: saturate(0) brightness(1.8); transform: scale(1.01); }
|
60% { transform: scale(1.01); }
|
||||||
70% { filter: hue-rotate(180deg) brightness(0.3); transform: none; }
|
70% { transform: none; }
|
||||||
80% { filter: contrast(5) saturate(0); transform: skewX(-1deg); }
|
80% { transform: skewX(-1deg); }
|
||||||
90% { filter: brightness(0.1); transform: scale(0.99); opacity: 0.1; }
|
90% { transform: none; }
|
||||||
100% { filter: brightness(0); transform: none; opacity: 0; }
|
100% { transform: none; }
|
||||||
|
}
|
||||||
|
.hero-glitch-filter {
|
||||||
|
animation: hero-glitch-filter 3s ease-in forwards !important;
|
||||||
|
position: fixed !important;
|
||||||
|
inset: 0 !important;
|
||||||
|
z-index: 99999 !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
@keyframes hero-glitch-filter {
|
||||||
|
0% { backdrop-filter: none; background: transparent; }
|
||||||
|
5% { backdrop-filter: hue-rotate(90deg) saturate(3); }
|
||||||
|
10% { backdrop-filter: invert(1); }
|
||||||
|
15% { backdrop-filter: hue-rotate(180deg) brightness(1.5); }
|
||||||
|
20% { backdrop-filter: saturate(5) contrast(2); }
|
||||||
|
25% { backdrop-filter: invert(1) hue-rotate(270deg); }
|
||||||
|
30% { backdrop-filter: brightness(2) saturate(0); }
|
||||||
|
40% { backdrop-filter: hue-rotate(45deg) contrast(3); }
|
||||||
|
50% { backdrop-filter: invert(1) brightness(0.5); }
|
||||||
|
60% { backdrop-filter: saturate(0) brightness(1.8); }
|
||||||
|
70% { backdrop-filter: hue-rotate(180deg) brightness(0.3); }
|
||||||
|
80% { backdrop-filter: contrast(5) saturate(0); }
|
||||||
|
90% { backdrop-filter: brightness(0); background: #000; }
|
||||||
|
100% { backdrop-filter: brightness(0); background: #000; }
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
|
|
||||||
const children = Array.from(wrapper.children) as HTMLElement[];
|
// Overlay for backdrop-filter (color distortion — works on all platforms)
|
||||||
children.forEach(child => child.classList.add("hero-glitch-child"));
|
const overlay = document.createElement("div");
|
||||||
|
overlay.className = "hero-glitch-filter";
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
|
||||||
|
// Shake transforms on all layout elements
|
||||||
|
const targets = document.querySelectorAll<HTMLElement>(
|
||||||
|
"header, main, footer, nav"
|
||||||
|
);
|
||||||
|
targets.forEach(el => el.classList.add("hero-glitch-shake"));
|
||||||
|
|
||||||
// After glitch animation, transition to void phase
|
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
children.forEach(child => child.classList.remove("hero-glitch-child"));
|
targets.forEach(el => el.classList.remove("hero-glitch-shake"));
|
||||||
|
overlay.remove();
|
||||||
style.remove();
|
style.remove();
|
||||||
setPhase("void");
|
setPhase("void");
|
||||||
}, 3000);
|
}, 3000);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
children.forEach(child => child.classList.remove("hero-glitch-child"));
|
targets.forEach(el => el.classList.remove("hero-glitch-shake"));
|
||||||
|
overlay.remove();
|
||||||
style.remove();
|
style.remove();
|
||||||
};
|
};
|
||||||
}, [phase]);
|
}, [phase]);
|
||||||
@@ -587,7 +626,7 @@ export default function Hero() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (phase === "glitch") {
|
if (phase === "glitch") {
|
||||||
return <div ref={glitchRef} className="min-h-screen" />;
|
return <div className="min-h-screen" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phase === "countdown") {
|
if (phase === "countdown") {
|
||||||
|
|||||||
@@ -151,28 +151,20 @@ export default function VoidExperience({ token }: VoidExperienceProps) {
|
|||||||
const [visitCount, setVisitCount] = useState<number | null>(null);
|
const [visitCount, setVisitCount] = useState<number | null>(null);
|
||||||
const [dissolving, setDissolving] = useState(false);
|
const [dissolving, setDissolving] = useState(false);
|
||||||
|
|
||||||
// Inject CSS + hide cursor + force fullscreen feel on mobile
|
// Inject CSS + hide cursor + hide layout chrome underneath
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const style = document.createElement("style");
|
const style = document.createElement("style");
|
||||||
style.textContent = GLITCH_CSS;
|
style.textContent = GLITCH_CSS;
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
document.body.style.cursor = "none";
|
document.body.style.cursor = "none";
|
||||||
|
|
||||||
// Push mobile tab bar off-screen by making the page taller than viewport
|
|
||||||
const meta = document.querySelector('meta[name="viewport"]');
|
|
||||||
const origContent = meta?.getAttribute("content") || "";
|
|
||||||
meta?.setAttribute("content", "width=device-width, initial-scale=1, interactive-widget=resizes-content");
|
|
||||||
document.documentElement.style.overflow = "hidden";
|
document.documentElement.style.overflow = "hidden";
|
||||||
document.body.style.overflow = "hidden";
|
document.body.style.overflow = "hidden";
|
||||||
// Scroll down slightly to trigger mobile browsers hiding the tab bar
|
|
||||||
window.scrollTo(0, 1);
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
style.remove();
|
style.remove();
|
||||||
document.body.style.cursor = "";
|
document.body.style.cursor = "";
|
||||||
document.documentElement.style.overflow = "";
|
document.documentElement.style.overflow = "";
|
||||||
document.body.style.overflow = "";
|
document.body.style.overflow = "";
|
||||||
if (meta) meta.setAttribute("content", origContent);
|
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -212,7 +204,7 @@ export default function VoidExperience({ token }: VoidExperienceProps) {
|
|||||||
const corruption = getCorruption(activeSegment);
|
const corruption = getCorruption(activeSegment);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed inset-0 bg-black" style={{ height: "100dvh" }}>
|
<div className="fixed inset-0 bg-black z-[9999]" style={{ height: "100dvh" }}>
|
||||||
{/* 3D Canvas — full glitch (transforms + filters) */}
|
{/* 3D Canvas — full glitch (transforms + filters) */}
|
||||||
<div className={`fixed inset-0 z-[10] ${getCanvasGlitch(activeSegment, dissolving)}`}>
|
<div className={`fixed inset-0 z-[10] ${getCanvasGlitch(activeSegment, dissolving)}`}>
|
||||||
<Canvas
|
<Canvas
|
||||||
@@ -225,17 +217,16 @@ export default function VoidExperience({ token }: VoidExperienceProps) {
|
|||||||
</Canvas>
|
</Canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Typewriter — filter-only glitch (no transform shift) */}
|
{/* Typewriter — glitch class applied to inner text, not the fixed container */}
|
||||||
{visitCount !== null && (
|
{visitCount !== null && (
|
||||||
<div className={getTextGlitch(activeSegment, dissolving)}>
|
<VoidTypewriter
|
||||||
<VoidTypewriter
|
startSegment={0}
|
||||||
startSegment={0}
|
onPhaseComplete={handlePhaseComplete}
|
||||||
onPhaseComplete={handlePhaseComplete}
|
onSegmentChange={handleSegmentChange}
|
||||||
onSegmentChange={handleSegmentChange}
|
visitCount={visitCount}
|
||||||
visitCount={visitCount}
|
corruption={corruption}
|
||||||
corruption={corruption}
|
glitchClass={getTextGlitch(activeSegment, dissolving)}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ interface VoidTypewriterProps {
|
|||||||
onSegmentChange: (index: number) => void;
|
onSegmentChange: (index: number) => void;
|
||||||
visitCount: number;
|
visitCount: number;
|
||||||
corruption: number;
|
corruption: number;
|
||||||
|
glitchClass: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTextNodes(node: Node): Text[] {
|
function getTextNodes(node: Node): Text[] {
|
||||||
@@ -25,7 +26,7 @@ function getTextNodes(node: Node): Text[] {
|
|||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function VoidTypewriter({ startSegment, onPhaseComplete, onSegmentChange, visitCount, corruption }: VoidTypewriterProps) {
|
export default function VoidTypewriter({ startSegment, onPhaseComplete, onSegmentChange, visitCount, corruption, glitchClass }: VoidTypewriterProps) {
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const corruptionRef = useRef(corruption);
|
const corruptionRef = useRef(corruption);
|
||||||
corruptionRef.current = corruption;
|
corruptionRef.current = corruption;
|
||||||
@@ -85,7 +86,7 @@ export default function VoidTypewriter({ startSegment, onPhaseComplete, onSegmen
|
|||||||
<div className="fixed inset-0 z-[50] flex justify-center items-center pointer-events-none">
|
<div className="fixed inset-0 z-[50] flex justify-center items-center pointer-events-none">
|
||||||
<div
|
<div
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
className="text-xl md:text-3xl font-bold text-center max-w-[85vw] md:max-w-[70vw] break-words text-white leading-relaxed"
|
className={`text-xl md:text-3xl font-bold text-center max-w-[85vw] md:max-w-[70vw] break-words text-white leading-relaxed ${glitchClass}`}
|
||||||
>
|
>
|
||||||
<Typewriter
|
<Typewriter
|
||||||
key={`void-${startSegment}-${visitCount}`}
|
key={`void-${startSegment}-${visitCount}`}
|
||||||
|
|||||||
@@ -44,14 +44,20 @@ Install the following programs. These will be needed to compile coreboot and fla
|
|||||||
|
|
||||||
<Commands
|
<Commands
|
||||||
description="Install prerequisite packages"
|
description="Install prerequisite packages"
|
||||||
archCommand="sudo pacman -S base-devel curl git gcc-ada ncurses zlib nasm sharutils unzip flashrom"
|
archCommand="sudo pacman -S base-devel curl git gcc-ada ncurses zlib nasm sharutils unzip flashrom usbutils chafa libwebp"
|
||||||
debianCommand="sudo apt install build-essential curl git gnat libncurses-dev zlib1g-dev nasm sharutils unzip flashrom"
|
debianCommand="sudo apt install build-essential curl git gnat libncurses-dev zlib1g-dev nasm sharutils unzip flashrom usbutils chafa webp"
|
||||||
fedoraCommand="sudo dnf install @development-tools curl git gcc-gnat ncurses-devel zlib-devel nasm sharutils unzip flashrom"
|
fedoraCommand="sudo dnf install @development-tools curl git gcc-gnat ncurses-devel zlib-devel nasm sharutils unzip flashrom usbutils chafa libwebp-tools"
|
||||||
gentooCommand="sudo emerge --ask sys-devel/base-devel net-misc/curl dev-vcs/git sys-devel/gcc ncurses dev-libs/zlib dev-lang/nasm app-arch/sharutils app-arch/unzip sys-apps/flashrom"
|
gentooCommand="sudo emerge --ask sys-devel/base-devel net-misc/curl dev-vcs/git sys-devel/gcc ncurses dev-libs/zlib dev-lang/nasm app-arch/sharutils app-arch/unzip sys-apps/flashrom sys-apps/usbutils media-gfx/chafa media-libs/libwebp"
|
||||||
nixCommand="nix-env -i stdenv curl git gcc gnat ncurses zlib nasm sharutils unzip flashrom"
|
nixCommand="nix-env -i stdenv curl git gcc gnat ncurses zlib nasm sharutils unzip flashrom usbutils chafa libwebp"
|
||||||
client:load
|
client:load
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
`usbutils` provides `lsusb` (used to verify the CH341A). `chafa` and the
|
||||||
|
`libwebp` tools are optional — the interactive script uses them to render
|
||||||
|
reference images inline in your terminal when supported (and to transcode
|
||||||
|
webp images to png if your chafa build doesn't support webp natively).
|
||||||
|
Without them the script falls back to printing a URL.
|
||||||
|
|
||||||
## Disassembling the Laptop
|
## Disassembling the Laptop
|
||||||
1. **Power off your laptop**: Make sure your T440p is completely powered off and unplugged from any power source.
|
1. **Power off your laptop**: Make sure your T440p is completely powered off and unplugged from any power source.
|
||||||
2. **Remove the battery**: Flip the laptop over and remove the battery by sliding the latch to the unlock position and lifting it out.
|
2. **Remove the battery**: Flip the laptop over and remove the battery by sliding the latch to the unlock position and lifting it out.
|
||||||
@@ -59,24 +65,39 @@ Install the following programs. These will be needed to compile coreboot and fla
|
|||||||
|
|
||||||
## Locating the EEPROM Chips
|
## Locating the EEPROM Chips
|
||||||
|
|
||||||
In order to flash the laptop, you will need to have access to two EEPROM chips located next to the sodimm RAM.
|
In order to flash the laptop, you will need to have access to two EEPROM chips
|
||||||
|
located next to the SODIMM RAM. They are different sizes and hold different
|
||||||
|
firmware — read them in the order shown below.
|
||||||
|
|
||||||

|
The **4MB (top)** chip — smaller, farther from the CPU:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The **8MB (bottom)** chip — larger, closer to the CPU, holds the Intel ME firmware:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Assembling the SPI Flasher
|
## Assembling the SPI Flasher
|
||||||
|
|
||||||
Place the SPI flasher ribbon cable into the correct slot and make sure its the 3.3v variant
|
Place the SPI flasher ribbon cable into the correct slot and make sure its the 3.3v variant
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
After the flasher is ready, connect it to your machine and ensure its ready to use:
|
After the flasher is ready, plug it into a USB port on your machine (leave the clip
|
||||||
|
unattached for now) and confirm the kernel sees it:
|
||||||
|
|
||||||
<Command
|
<Command
|
||||||
description="Ensure the CH341A flasher is being detected"
|
description="Verify CH341A is on the USB bus"
|
||||||
command="flashrom --programmer ch341a_spi"
|
command="lsusb | grep 1a86:5512"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Flashrom should report that programmer initialization was a success.
|
A matching line (e.g. `Bus 001 Device 00X: ID 1a86:5512 QinHeng Electronics`)
|
||||||
|
confirms the programmer is plugged in and the host recognises it.
|
||||||
|
|
||||||
|
> Do **not** run `flashrom --programmer ch341a_spi` at this stage — with no
|
||||||
|
> chip clipped on, flashrom will report "No EEPROM/flash device found" and
|
||||||
|
> exit non-zero. That's expected, not a failure of the programmer. The chip
|
||||||
|
> probe happens in the next section, paired with the actual read.
|
||||||
|
|
||||||
## Extracting Original BIOS
|
## Extracting Original BIOS
|
||||||
|
|
||||||
@@ -89,11 +110,14 @@ the T440p will be done.
|
|||||||
client:load
|
client:load
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Next, extract the original rom from both EEPROM chips. This is
|
Next, extract the original ROM from both EEPROM chips. Do the **4MB (top)
|
||||||
done by attaching the programmer to the correct chip and running
|
chip first** — it's the smaller of the two, so reads finish faster and any
|
||||||
the subsequent commands. It may take longer than expected, and
|
setup issues (clip alignment, pin 1, voltage) surface quickly. Then move
|
||||||
ensuring the bios was properly extracted is important before proceeding
|
the clip to the **8MB (bottom) chip**.
|
||||||
further.
|
|
||||||
|
Each chip is read twice so the two reads can be diffed to catch flaky
|
||||||
|
contact. The reads can take a while (tens of seconds to a couple of
|
||||||
|
minutes per pass) — that's normal.
|
||||||
|
|
||||||
<CommandSequence
|
<CommandSequence
|
||||||
commands={[
|
commands={[
|
||||||
@@ -115,11 +139,18 @@ further.
|
|||||||
client:load
|
client:load
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
> **If flashrom errors with "Multiple flash chip definitions match":**
|
||||||
|
> Your chip's silicon ID matches several part variants (common for Winbond
|
||||||
|
> W25Q* parts). Re-run the command with `-c <chipname>` to disambiguate, e.g.
|
||||||
|
> `sudo flashrom --programmer ch341a_spi -c W25Q32JV -r 4mb_backup1.bin`.
|
||||||
|
> Use the same `-c` value for every subsequent read/write on that chip.
|
||||||
|
> The newest variant in the list is usually a safe default.
|
||||||
|
|
||||||
If the diff checks pass, combine both files into one ROM.
|
If the diff checks pass, combine both files into one ROM.
|
||||||
|
|
||||||
<Command
|
<Command
|
||||||
description="Combine 4MB & 8MB into one ROM"
|
description="Combine 4MB & 8MB into one ROM"
|
||||||
command="cat 8mb_backup_1.bin 4mb_backup1.bin > t440p-original.rom"
|
command="cat 8mb_backup1.bin 4mb_backup1.bin > t440p-original.rom"
|
||||||
client:load
|
client:load
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -140,7 +171,7 @@ a new bios image.
|
|||||||
client:load
|
client:load
|
||||||
/>
|
/>
|
||||||
|
|
||||||
We will need to build `idftool`, which will be used to export all necessary blobs
|
We will need to build `ifdtool`, which will be used to export all necessary blobs
|
||||||
from our original bios, and `cbfstool`, which will be used to extract __mrc.bin__(a blob
|
from our original bios, and `cbfstool`, which will be used to extract __mrc.bin__(a blob
|
||||||
from a haswell chromebook peppy image).
|
from a haswell chromebook peppy image).
|
||||||
|
|
||||||
@@ -258,9 +289,14 @@ Then open the configuration menu:
|
|||||||
Key settings to configure:
|
Key settings to configure:
|
||||||
|
|
||||||
- **Mainboard** → Mainboard vendor: **Lenovo** → Mainboard model: **ThinkPad T440p**
|
- **Mainboard** → Mainboard vendor: **Lenovo** → Mainboard model: **ThinkPad T440p**
|
||||||
- **Chipset** → Add Intel descriptor.bin, ME firmware, and GbE configuration (set paths to your blobs)
|
(`CONFIG_BOARD_LENOVO_THINKPAD_T440P=y`)
|
||||||
- **Chipset** → Add haswell MRC file (set path to mrc.bin)
|
- **Chipset** → Add Intel descriptor.bin (`CONFIG_HAVE_IFD_BIN`), ME firmware (`CONFIG_HAVE_ME_BIN`),
|
||||||
- **Payload** → Choose your preferred payload (GRUB2, SeaBIOS, or edk2)
|
and GbE configuration (`CONFIG_HAVE_GBE_BIN`) — set paths to your extracted blobs.
|
||||||
|
- **Chipset** → Add Haswell MRC file (`CONFIG_HAVE_MRC` / `CONFIG_MRC_FILE`) — set path to `mrc.bin`.
|
||||||
|
- **Payload** → Choose your preferred payload: GRUB2 (`CONFIG_PAYLOAD_GRUB2`), SeaBIOS
|
||||||
|
(`CONFIG_PAYLOAD_SEABIOS`), or Tianocore/edk2 (`CONFIG_PAYLOAD_TIANOCORE`).
|
||||||
|
- **Devices** → (optional, GT730M only) Enable `CONFIG_VGA_BIOS_DGPU` and set
|
||||||
|
`CONFIG_VGA_BIOS_DGPU_FILE` to your extracted GT730M VBIOS (PCI ID `10de,1292`).
|
||||||
|
|
||||||
## Building and Flashing
|
## Building and Flashing
|
||||||
|
|
||||||
@@ -344,7 +380,7 @@ Reboot to apply `iomem=relaxed`
|
|||||||
|
|
||||||
<Command
|
<Command
|
||||||
description="Flash the original bios"
|
description="Flash the original bios"
|
||||||
command="sudo flashrom -p internal:laptop=force_I_want_a_brick -r ~/t440p-coreboot/t440p-original.rom"
|
command="sudo flashrom -p internal:laptop=force_I_want_a_brick -w ~/t440p-coreboot/t440p-original.rom"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
And that about wraps it up! If you liked the guide, leave a reaction or comment any changes or fixes
|
And that about wraps it up! If you liked the guide, leave a reaction or comment any changes or fixes
|
||||||
|
|||||||
Reference in New Issue
Block a user