Table of Contents

Advertisement

Pocket Linux Guide
David Horton
<dhorton<AT>NOSPAM.member.fsf.org>
Revision History
Revision 3.1
Minor clarifications and spelling corrections.
Revision 3.0
Changed bootloader to GRUB rather than LILO. Updated versions on all source code packages. Made minor
clarifications to some shell commands and scripts.
Revision 2.1
Corrected typos. Changed resource site hosting to SourceForge. Added appendix B to include the GNU Free
Documentation License as part of this document.
Revision 2.0
Updated to use GNU coreutils in place of fileutils, sh−utils and textutils. Updated version numbers on many
source code packages. Introduced Freshmeat as a resource for finding source code. Changed /etc/mtab to a
real file rather than using a symlink to /proc/mounts. Corrected local_fs script errors. Updated email address.
Revision 1.2
Corrected errors in "strip −o library" commands.
Revision 1.1
Bug fixes, typo corrections and improved XML markup.
Revision 1.0
Initial Release, reviewed by LDP.
The Pocket Linux Guide is for anyone interested in learning the techniques of building a GNU/Linux system
from source code. The guide is structured as a project that builds a small diskette−based GNU/Linux system
called Pocket Linux. Each chapter explores a small piece of the overall system explaining how it works, why
it is needed and how to build it. After completing the Pocket Linux project, readers should possess an
enhanced knowledge of what makes GNU/Linux systems work as well as the confidence to explore larger,
more complex source−code−only projects.
2005−04−09
2004−11−02
2004−02−18
2003−11−08
2003−05−31
2003−05−21
2003−02−17
Revised by: DH
Revised by: DH
Revised by: DH
Revised by: DH
Revised by: DH
Revised by: DH
Revised by: DH

Advertisement

Table of Contents
loading
Need help?

Need help?

Do you have a question about the Pocket Linux Guide and is the answer not in the manual?

Questions and answers

Summary of Contents for Linux Pocket Linux Guide

  • Page 1 Revised by: DH Initial Release, reviewed by LDP. The Pocket Linux Guide is for anyone interested in learning the techniques of building a GNU/Linux system from source code. The guide is structured as a project that builds a small diskette−based GNU/Linux system called Pocket Linux.
  • Page 2: Table Of Contents

    2.3.2. Build the GRUB bootloader....................7 2.3.3. Copy the bootloader files to diskette..................8 2.3.4. Finish bootloader installation....................8 2.3.5. Build the Linux kernel ......................8 2.3.6. Copy the kernel to diskette......................9 2.3.7. Unmount the boot disk......................9 2.3.8. Prepare the root disk media.....................9 2.3.9.
  • Page 3 5.2.3. Automating fsck and mount....................22 5.2.4. File dependencies........................22 5.3. Construction............................23 5.3.1. Install utilities from e2fsprogs ....................23 5.3.2. Install utilities from util−linux....................23 5.3.3. Check library requirements....................24 5.3.4. Strip binaries to save space....................24 5.3.5. Create additional device files....................24 5.3.6. Create the fstab and mtab files....................24...
  • Page 4 Pocket Linux Guide Table of Contents Chapter 5. Checking and Mounting Disks 5.3.7. Write a script to check and mount local filesystems.............24 5.3.8. Create a compressed root disk image..................25 5.3.9. Write the root disk image to floppy ..................25 5.4. Implementation..........................25 5.4.1.
  • Page 5 Pocket Linux Guide Table of Contents Chapter 7. Enabling Multiple Users 7.3.6. Set directory and file permissions..................39 7.3.7. Create the root disk image.....................40 7.3.8. Copy the image to diskette....................40 7.4. Implementation..........................40 7.4.1. System Startup ........................40 7.4.2. Add a new user to the system....................40 7.4.3.
  • Page 6 Pocket Linux Guide Table of Contents Appendix A. Hosting Applications A.3.2. Create an enhanced root disk ....................51 A.3.3. Create a compressed /usr disk for mp3blaster..............53 A.3.4. Create a data diskette for testing..................54 A.4. Implementation..........................54 A.4.1. System Startup........................54 A.4.2. Verify that the /usr diskette loaded properly................54 A.4.3.
  • Page 7: Legal Information

    Legal Information 1. Copyright and License This document, Pocket Linux Guide, is copyright (c) 2003 − 2005 by David Horton. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front−Cover Texts, and with no Back−Cover Texts.
  • Page 8: Introduction

    The Pocket Linux Guide demonstrates how to build a small console−based GNU/Linux system using only source code and a couple of diskettes. It is intended for Linux users who would like to gain a deeper understanding about how their system works beneath the shroud of distribution specific features and tools.
  • Page 9: Feedback

    Additional projects that may be of interest to Pocket Linux Guide readers. 5. Feedback For technical questions about Pocket Linux please use the mailing list or the troubleshooting forum on the resource site. General comments and suggestions may be sent to the mailing list or emailed to the author directly.
  • Page 10: Chapter 1. Project Initiation

    Being a Linux Expert now means knowing which button to click in the GUI administration tool. Recently there has been a yearn for a return to the "good old days" of Linux when men were men, sysadmins were hardcore geeks and everything was compiled from source code. A notable indication of this movement was the publication of the Linux−From−Scratch−HOWTO version 1.0 by Gerard Beekmans in 1999.
  • Page 11 Pocket Linux Guide To further reduce the time commitment, the Pocket Linux project is divided into several phases, each one chapter in length. Each phase builds only a small piece of the overall project, but at the same time the conclusion of each chapter results in a self−contained, working system.
  • Page 12: Chapter 2. A Simple Prototype

    2.2.2. Boot Disk For the boot disk we simply need to install the GRUB bootloader and a Linux kernel. We will need to use a kernel that does not require modules for the hardware we need to access. Mainly, it should have compiled−in support for the floppy drive, ram disk, second extended filesystem, proc filesystem, ELF binaries, and a text−based console.
  • Page 13: Root Disk

    486 or 386. So a kernel optimized for a new, fast 6x86 machine will not run on an older box. (See the README file in the Linux kernel source code for details.) A BASH shell built for a 6x86 will probably not run on an older processor either.
  • Page 14: Copy The Bootloader Files To Diskette

    2.3.5. Build the Linux kernel The steps for building the kernel were tested using Linux kernel version 2.4.26 and should work any 2.4.x or 2.6.x kernel. The latest version of the kernel source code may be downloaded from http://www.kernel.org/ or one of its mirrors.
  • Page 15: Copy The Kernel To Diskette

    Pocket Linux Guide 2.3.6. Copy the kernel to diskette bash# cp /usr/src/linux/arch/i386/boot/bzImage /mnt/boot/vmlinuz 2.3.7. Unmount the boot disk bash# cd / bash# umount /mnt 2.3.8. Prepare the root disk media Insert a blank diskette labeled "root disk". bash# mke2fs −m0 /dev/fd0 bash# mount /dev/fd0 /mnt 2.3.9.
  • Page 16: Implementation

    Pocket Linux Guide 2.4. Implementation 2.4.1. System startup Follow these steps to boot the system: Restart the PC with the boot disk in the floppy drive. When the grub> prompt appears, type kernel (fd0)/boot/vmlinuz init=/bin/sh root=/dev/fd0 load_ramdisk=1 prompt_ramdisk=1 and press Enter.
  • Page 17: System Shutdown

    Pocket Linux Guide 2.4.4. System shutdown Remove the diskette from fd0 and restart the system using CTRL−ALT−DELETE. Chapter 2. A Simple Prototype...
  • Page 18: Chapter 3. Saving Space

    Chapter 3. Saving Space 3.1. Analysis One of the drawbacks in the prototype phase of the project was that the diskset was not all that useful. The only commands that worked were the ones built into the BASH shell. We could improve our root disk by installing commands like cat, ls, mv, rm and so on.
  • Page 19: Construction

    Pocket Linux Guide that if the root filesystem is going to be run from a ramdisk, it may as well be built on a ramdisk. All we have to do is create a second extended filesystem on a ramdisk device, mount it and copy files to it. Once the filesystem is populated with all the files that the root disk needs, we simply unmount it, compress it and write it out to floppy.
  • Page 20: Create A Console Device

    3.4. Implementation Successful implementation of this phase is probably the most difficult part of the Pocket Linux Guide. If you need help getting things to work please visit the Pocket Linux Guide Resource Site to browse the troubleshooting forum and subscribe to the mailing list.
  • Page 21: Verify Results

    Pocket Linux Guide grub> kernel (fd0)/boot/vmlinuz init=/bin/sh root=/dev/fd0 load_ramdisk=1 prompt_ramdisk=1 [Linux−bzImage, setup=0xc00, size=0xce29b] grub> boot Linux version 2.4.26 .. [various kernel messages] VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER RAMDISK: Compressed image found at block 0 VFS: Mounted root (ext2 filesystem) readonly.
  • Page 22: Chapter 4. Some Basic Utilities

    We can either search the manpages included with one of the popular GNU/Linux distributions or use one of the manpage search engines listed at http://www.tldp.org/docs.html#man. One thing that should tip us off as to where to find the source code for a particular command is the email address listed for reporting bugs.
  • Page 23: Downloading Source Code

    Pocket Linux Guide GNU fileutils −− chgrp, chmod, chown, cp, dd, df, ln, ls, mkdir, mknod, mv, rm, rmdir, sync GNU sh−utils −− date, hostname, stty, su, uname These four packages do not contain all of the commands in the /bin directory, but they do represent of over 70% of them.
  • Page 24: Install Binaries From Gnu Coreutils

    Pocket Linux Guide 4.3.3. Install binaries from GNU coreutils Download a recent version of coreutils from ftp://ftp.gnu.org/gnu/coreutils/ bash# cd /usr/src/coreutils−5.2.1 bash# export CC="gcc −mcpu=i386" bash# ./configure −−host=i386−pc−linux−gnu bash# make bash# cd src bash# cp cat chgrp chmod chown cp date dd df ~/staging/bin...
  • Page 25: Implementation

    Pocket Linux Guide 4.4. Implementation We will need to have a read−write filesystem in order for some of the commands to work. The kernel's normal behavior is to mount root as read−only, but we can change this using a kernel option. By passing the kernel the rw option before init=/bin/sh we will get a read−write root filesystem.
  • Page 26: System Shutdown

    Pocket Linux Guide 4.4.3. System shutdown Remove the diskette from fd0 and restart the system using CTRL−ALT−DELETE. Chapter 4. Some Basic Utilities...
  • Page 27: Chapter 5. Checking And Mounting Disks

    Network filesystems are mounted. So far our Pocket Linux system can do step one and that is it. If we want to have a professional looking boot / root diskset we will have to do better than one out of five. In this phase of the project we will work on steps two and three.
  • Page 28: Automating Fsck And Mount

    LSM comes up with a number of matches, but most of them point to various versions of a package called util−linux. All we have to do is scroll through and pick the most recent release. The LSM entry for util−linux lists a lot of utilities besides just mount and umount.
  • Page 29: Construction

    ~/staging/sbin bash# ln −s mke2fs ~/staging/sbin/mkfs.ext2 5.3.2. Install utilities from util−linux Get the latest util−linux source from ftp://ftp.win.tue.nl/pub/linux−local/utils/util−linux/ bash# cd /usr/src/util−linux−2.12h Use a text editor to make the following changes to MCONFIG: Change "CPU=$(shell uname −m)" to "CPU=i386"...
  • Page 30: Check Library Requirements

    Pocket Linux Guide bash# make bash# cp disk−utils/mkfs ~/staging/sbin bash# cp fdisk/fdisk ~/staging/sbin bash# cp login−utils/agetty ~/staging/sbin bash# ln −s agetty ~/staging/sbin/getty bash# cp login−utils/login ~/staging/bin bash# cp misc−utils/kill ~/staging/bin bash# cp mount/mount ~/staging/bin bash# cp mount/umount ~/staging/bin bash# cp mount/swapon ~/staging/sbin bash# cp sys−utils/dmesg ~/staging/bin...
  • Page 31: Create A Compressed Root Disk Image

    Pocket Linux Guide fsck −ATCp if [ $? −gt 1 ]; then echo "Filesystem errors still exist! Manual intervention required." /bin/sh else echo "Remounting / as read−write." mount −n −o remount,rw / echo −n >/etc/mtab mount −f −o remount,rw / echo "Mounting local filesystems."...
  • Page 32: Test The Local_Fs Script

    Pocket Linux Guide [Linux−bzImage, setup=0xc00, size=0xce29b] grub> boot Linux version 2.4.26 .. [various kernel messages] VFS: Insert root floppy disk to be loaded into RAM disk and press ENTER RAMDISK: Compressed image found at block 0 VFS: Mounted root (ext2 filesystem) readonly.
  • Page 33 Pocket Linux Guide Remove the diskette from fd0 and restart the system using CTRL−ALT−DELETE. Chapter 5. Checking and Mounting Disks...
  • Page 34: Chapter 6. Automating Startup & Shutdown

    But even with all of this the root disk is far from perfect. The list below outlines three things that could use some improvement if the Pocket Linux system is to stand up next to the more professional looking distributions.
  • Page 35: Checking Dependencies

    6.2.5. Outlining start−up scripts Many of the popular GNU/Linux distributions use System V style init scripts. Since we are using a "sysvinit" daemon it makes sense to use System V style scripts as well. The following documents all touch upon the System V style init scripts in some way and will serve as references when building the scripts for this project: The Debian Policy Manual −−...
  • Page 36: Construction

    Use your favorite text editor to create the following file and save it as /mnt/boot/grub/menu.lst: default 0 timeout 3 title Pocket Linux Boot Disk kernel (fd0)/boot/vmlinuz root=/dev/fd0 load_ramdisk=1 prompt_ramdisk=1 6.3.2. Install sysvinit utilities Download the latest sysvinit source from ftp://ftp.cistron.nl/pub/people/miquels/software/ bash# cd /usr/src/sysvinit−2.85/src...
  • Page 37: Create /Etc/Init.d/Rc Script

    Pocket Linux Guide # end of /etc/inittab 6.3.4. Create /etc/init.d/rc script Use a text editor to create the following file and save it as ~/staging/etc/init.d/rc #!/bin/sh # /etc/init.d/rc − runlevel change script PATH=/sbin:/bin SCRIPT_DIR="/etc/rc$1.d" # Check that the rcN.d directory really exists.
  • Page 38: Create A Hostname Script

    Pocket Linux Guide else echo "Remounting / as read−write." mount −n −o remount,rw / echo −n > /etc/mtab mount −f −o remount,rw / echo "Mounting local filesystems." mount −a −t nonfs,smbfs stop) echo "Unmounting local filesystems." umount −a −r echo "usage: $0 start|stop";...
  • Page 39: Create Rcn.d Directories And Links

    Pocket Linux Guide #!/bin/sh # reboot − reboot the system PATH=/sbin:/bin ; export PATH echo "Initiating system reboot." reboot # end of /etc/init.d/reboot Flag all script files as executable. bash# chmod +x ~/staging/etc/init.d/* 6.3.8. Create rcN.d directories and links bash# cd ~/staging/etc bash# mkdir rc0.d rc1.d rc2.d rc3.d rc4.d rc5.d rc6.d rcS.d...
  • Page 40: Verify Success Of Startup Scripts

    Pocket Linux Guide Uncompressing Linux... Ok, booting kernel. .. [various kernel messages] VFS: Insert root floppy to be loaded into RAM disk and press ENTER RAMDISK: Compressed image found at block 0 VFS: Mounted root (ext2 filesystem) readonly. Freeing unused kernel memory: 178k freed Checking local filesystem integrity.
  • Page 41: Chapter 7. Enabling Multiple Users

    If everything is okay the user's shell is started. 7.2.2. Obtaining source code The getty and login programs were already installed as part of the util−linux package so there is no need to download any new source code. 7.2.3. Creating support files 7.2.3.1.
  • Page 42: Dependencies

    "root" with no password, a group id of zero and the user root assigned to it as the only member. 7.2.3.5. Conventions User and group names and id's are generally not chosen at random. Most Linux systems have very similar looking /etc/passwd and /etc/group files. Definitions for commonly used user id and group id assignments may be found in one of several places: The /etc/passwd and /etc/group files on any popular GNU/Linux distribution.
  • Page 43: Construction

    Pocket Linux Guide contains commands that may be used by both the system administrator and by users". From that statement we can infer that /bin should have read and execute permission for everyone. On the other hand, the /boot directory contains files for the boot loader. Chances are good that regular users will not need to access anything in the /boot directory.
  • Page 44: Create Tty Devices

    Be sure that "\l" is a lowercase letter L and not the number one. 7.3.4.2. /etc/passwd Use a text editor to create a minimal passwd file conforming to the Linux Standards Base (LSB) document. Save the file as ~/staging/etc/passwd root::0:0:Super User:/root:/bin/sh...
  • Page 45: Copy Required Libraries

    Pocket Linux Guide 7.3.5. Copy required libraries bash# cp /lib/libnss_files.so.2 ~/staging/lib bash# strip −−strip−unneeded ~/staging/lib/* 7.3.6. Set directory and file permissions Set minimal privileges on all files and directories under ~/staging. Everything is owned by the root user and the root group. Permissions are read−write for the owner and read−only for the group. Exceptions to the blanket permissions are handled case by case.
  • Page 46: Create The Root Disk Image

    Pocket Linux Guide 7.3.7. Create the root disk image bash# cd / bash# dd if=/dev/zero of=/dev/ram7 bs=1k count=4096 bash# mke2fs −m0 /dev/ram7 4096 bash# mount /dev/ram7 /mnt bash# cp −dpR ~/staging/* /mnt bash# umount /dev/ram7 bash# dd if=/dev/ram7 of=~/phase6−image bs=1k count=4096 bash# gzip −9 ~/phase6−image...
  • Page 47: System Shutdown

    Pocket Linux Guide Try the following commands and verify that they do not work. bash$ ls /root bash$ /sbin/shutdown −h now bash$ su − 7.4.4. System shutdown Switch back to tty1 where root is logged in. bash# shutdown −h now...
  • Page 48: Chapter 8. Filling In The Gaps

    8.2. Design 8.2.1. more There is a more command that comes with util−linux, but it will not work for this project. The reason is because of library dependencies and space constraints. The util−linux supplied more needs either the libncurses or libtermcap to work and there just is not enough space on the root disk floppy to fit everything in.
  • Page 49: More Device Files

    /dev files. The Linux Standard Base requires null, zero and tty to be present in the /dev directory. Files for null and tty already exist from previous phases of the project, but we still need /dev/zero. We can refer to devices.txt in the Linux source code Documentation directory for major and minor numbers.
  • Page 50: Create Additional Device Files

    Pocket Linux Guide # Initialize line counter variable let LINE_COUNTER=$LINES # Read the input file one line at a time and display on STDOUT until # the page fills up. Display "Press <Enter>" message on STDERR and wait # for keypress from STDERR.
  • Page 51: Install Ed

    Pocket Linux Guide 8.3.5. Install ed The ed package also comes from GNU at ftp://ftp.gnu.org/gnu/ed/ bash# cd /usr/src/ed−0.2 bash# ./configure −−host=i386−pc−linux−gnu bash# make bash# cp ed ~/staging/bin 8.3.6. Strip binaries to save space bash# strip ~/staging/bin/* 8.3.7. Ensure proper permissions bash# chown 0:0 ~/staging/bin/* bash# chmod −R 755 ~/staging/bin...
  • Page 52: Use Ps To Show Running Processes

    Pocket Linux Guide bash# more /etc/init.d/local_fs 8.4.3. Use ps to show running processes Display processes for the user currently logged in. bash# ps Display all available information about all running processes. bash# ps −ef 8.4.4. Run a simple sed script Use sed to display an alternate version of /etc/passwd.
  • Page 53: Chapter 9. Project Wrap Up

    Chapter 9. Project Wrap Up 9.1. Celebrating Accomplishments As the Pocket Linux Project draws to a close we should take a moment to celebrate all of our accomplishments. Some of the highlights are listed below: We have built a system, from source code only, that fully implements all of the commands described in the Filesystem Hierarchy Standard requirements for a root filesystem.
  • Page 54: Appendix A. Hosting Applications

    So what will it take to turn a pocket−sized GNU/Linux system into a pocket−sized mp3 player? A few things are listed below.
  • Page 55: Creating Space For The Program

    /dev. Typically the kernel supports eight ramdisks on /dev/ram0 through /dev/ram7 with ram0 being used for the rootdisk. The devices.txt file included in the Linux source code documentation will be helpful for matching devices to their major and minor numbers.
  • Page 56: Other Required Files

    /usr/share/terminfo directory and is very large compared to our available disk space. But, since Pocket Linux only supports the PC console, we only have one terminal type to worry about and therefore need only one file. The piece of the terminfo database we need is the file /usr/share/terminfo/l/linux, because we are using a "Linux"...
  • Page 57: Create An Enhanced Boot Disk

    Pocket Linux Guide A.3.1. Create an enhanced boot disk A.3.1.1. Build a new kernel bash# cd /usr/src/linux bash# make menuconfig Be sure to configure support for the following: 386 processor Floppy disk RAM disk Second extended (ext2) filesystem Virtual console Audio hardware CD−ROM hardware...
  • Page 58 Pocket Linux Guide A.3.2.1.3. Audio bash# mknod −m664 ~/staging/dev/dsp c 14 3 bash# mknod −m664 ~/staging/dev/mixer c 14 0 A.3.2.2. Install the gunzip binary bash# cd /usr/src/gzip−1.2.4a bash# export CC="gcc −mcpu=i386" bash# ./configure −−host=i386−pc−linux−gnu bash# make bash# strip gzip bash# cp gzip ~/staging/bin bash# ln −s gzip ~/staging/bin/gunzip...
  • Page 59: Create A Compressed /Usr Disk For Mp3Blaster

    Pocket Linux Guide bash# dd if=/dev/ram7 of=~/phase8−image bs=1k bash# gzip −9 ~/phase8−image Insert the diskette labeled "root disk" into drive fd0. bash# dd if=~/phase8−image.gz of=/dev/fd0 bs=1k A.3.3. Create a compressed /usr disk for mp3blaster The compressed /usr diskette will be created in using the same process that is used to create the compressed root disk.
  • Page 60: Create A Data Diskette For Testing

    A.4.5. Play a sample file Insert the diskette containing the sample audio file. mount /dev/fd0 /home bash# /usr/bin/mp3blaster Use mp3blaster to select and play the file /home/torvalds−says−linux.mp3. Use mp3blaster's mixer controls to adjust the volume as needed. Appendix A. Hosting Applications...
  • Page 61: System Shutdown

    Pocket Linux Guide A.4.6. System shutdown Bring the system down gracefully with the shutdown command. Appendix A. Hosting Applications...
  • Page 62: Appendix B. Gnu Free Documentation License

    Appendix B. GNU Free Documentation License Version 1.2, November 2002 Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111−1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. B.1.
  • Page 63: Verbatim Copying

    Pocket Linux Guide may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front−Cover Texts or Back−Cover Texts, in the notice that says that the Document is released under this License. A Front−Cover Text may be at most 5 words, and a Back−Cover Text may be at most 25 words.
  • Page 64: Copying In Quantity

    Pocket Linux Guide B.4. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front−Cover Texts on the front cover,...
  • Page 65: Combining Documents

    Pocket Linux Guide Include an unaltered copy of this License. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History"...
  • Page 66: Collections Of Documents

    Pocket Linux Guide contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.
  • Page 67: Termination

    Pocket Linux Guide B.10. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

Table of Contents

Save PDF