blob: 07f909ae84158b07c4daa2078aba107d6499db05 [file] [log] [blame]
srs5694e7b4ff92009-08-18 13:16:10 -04001// attributes.cc
2// Class to manage partition attribute codes. These are binary bit fields,
3// of which only three are currently (2/2009) documented on Wikipedia.
4
srs5694221e0872009-08-29 15:00:31 -04005/* This program is copyright (c) 2009 by Roderick W. Smith. It is distributed
6 under the terms of the GNU GPL version 2, as detailed in the COPYING file. */
7
srs5694e7b4ff92009-08-18 13:16:10 -04008#define __STDC_LIMIT_MACROS
9#define __STDC_CONSTANT_MACROS
10
srs5694e7b4ff92009-08-18 13:16:10 -040011#include <stdint.h>
12#include <stdio.h>
srs5694fed16d02010-01-27 23:03:40 -050013#include <iostream>
srs569408bb0da2010-02-19 17:19:55 -050014#include <sstream>
srs56949ddc14b2010-08-22 22:44:42 -040015
srs5694e7b4ff92009-08-18 13:16:10 -040016#include "attributes.h"
srs56949ddc14b2010-08-22 22:44:42 -040017#include "support.h"
srs5694e7b4ff92009-08-18 13:16:10 -040018
19using namespace std;
20
srs56949ddc14b2010-08-22 22:44:42 -040021string Attributes::atNames[NUM_ATR];
srs56940873e9d2010-10-07 13:00:45 -040022int Attributes::numAttrs = 0;
23//Attributes::staticInit Attributes::staticInitializer;
srs5694e7b4ff92009-08-18 13:16:10 -040024
srs56940873e9d2010-10-07 13:00:45 -040025// Default constructor
26Attributes::Attributes(void) {
27 numAttrs++;
28 if (numAttrs == 1)
29 Setup();
30 attributes = 0;
31} // constructor
32
33// Alternate constructor
34Attributes::Attributes(const uint64_t a) {
35 numAttrs++;
36 if (numAttrs == 1)
37 Setup();
38 attributes = a;
39} // alternate constructor
40
41// Destructor.
42Attributes::~Attributes(void) {
43 numAttrs--;
44} // Attributes destructor
45
46void Attributes::Setup(void) {
srs56949ddc14b2010-08-22 22:44:42 -040047 ostringstream temp;
srs56940873e9d2010-10-07 13:00:45 -040048
srs5694e7b4ff92009-08-18 13:16:10 -040049 // Most bits are undefined, so start by giving them an
50 // appropriate name
srs56949ddc14b2010-08-22 22:44:42 -040051 for (int i = 0; i < NUM_ATR; i++) {
52 temp.str("");
srs569408bb0da2010-02-19 17:19:55 -050053 temp << "Undefined bit #" << i;
srs56949ddc14b2010-08-22 22:44:42 -040054 Attributes::atNames[i] = temp.str();
srs5694e7b4ff92009-08-18 13:16:10 -040055 } // for
56
57 // Now reset those names that are defined....
srs56940873e9d2010-10-07 13:00:45 -040058 atNames[0] = "system partition"; // required for computer to operate
59 atNames[1] = "hide from EFI";
60 atNames[2] = "legacy BIOS bootable";
61 atNames[60] = "read-only";
62 atNames[62] = "hidden";
63 atNames[63] = "do not automount";
64} // Attributes::Setup()
srs5694e7b4ff92009-08-18 13:16:10 -040065
66// Display current attributes to user
67void Attributes::DisplayAttributes(void) {
srs56949ddc14b2010-08-22 22:44:42 -040068 uint32_t i;
69 int numSet = 0;
srs5694e7b4ff92009-08-18 13:16:10 -040070
srs5694fed16d02010-01-27 23:03:40 -050071 cout << "Attribute value is ";
72 cout.setf(ios::uppercase);
73 cout.fill('0');
74 cout.width(16);
75 cout << hex << attributes << dec << ". Set fields are:\n";
srs5694e7b4ff92009-08-18 13:16:10 -040076 for (i = 0; i < NUM_ATR; i++) {
srs56949ddc14b2010-08-22 22:44:42 -040077 if ((UINT64_C(1) << i) & attributes) {
srs56940873e9d2010-10-07 13:00:45 -040078 cout << i << " (" << GetAttributeName(i) << ")" << "\n";
srs56949ddc14b2010-08-22 22:44:42 -040079 numSet++;
srs5694e7b4ff92009-08-18 13:16:10 -040080 } // if
81 } // for
srs5694fed16d02010-01-27 23:03:40 -050082 cout.fill(' ');
srs56949ddc14b2010-08-22 22:44:42 -040083 if (numSet == 0)
84 cout << " No fields set\n";
85 cout << "\n";
srs5694e7b4ff92009-08-18 13:16:10 -040086} // Attributes::DisplayAttributes()
87
srs56940873e9d2010-10-07 13:00:45 -040088// Display attributes for a partition. Note that partNum is just passed for
89// immediate display; it's not used to access a particular partition.
90void Attributes::ShowAttributes(const uint32_t partNum) {
91 uint32_t bitNum;
92 bool bitset;
93
94 for (bitNum = 0; bitNum < 64; bitNum++) {
95 bitset = (UINT64_C(1) << bitNum) & attributes;
96 if (bitset) {
97 cout << partNum+1 << ":" << bitNum << ":" << bitset
98 << " (" << GetAttributeName(bitNum) << ")" << endl;
99 } // if
100 } // for
101} // Attributes::ShowAttributes
102
srs5694e7b4ff92009-08-18 13:16:10 -0400103// Prompt user for attribute changes
104void Attributes::ChangeAttributes(void) {
srs56949ddc14b2010-08-22 22:44:42 -0400105 int response;
srs5694e7b4ff92009-08-18 13:16:10 -0400106 uint64_t bitValue;
107
srs5694fed16d02010-01-27 23:03:40 -0500108 cout << "Known attributes are:\n";
srs56949ddc14b2010-08-22 22:44:42 -0400109 ListAttributes();
110 cout << "\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400111
112 do {
srs56949ddc14b2010-08-22 22:44:42 -0400113 DisplayAttributes();
srs56940873e9d2010-10-07 13:00:45 -0400114 response = GetNumber(0, NUM_ATR, 64,
115 "Toggle which attribute field (0-63, 64 or <Enter> to exit): ");
srs5694e7b4ff92009-08-18 13:16:10 -0400116 if (response != 64) {
srs56949ddc14b2010-08-22 22:44:42 -0400117 bitValue = UINT64_C(1) << response; // Find the integer value of the bit
118 if (bitValue & attributes) { // bit is set
119 attributes &= ~bitValue; // so unset it
120 cout << "Have disabled the '" << atNames[response] << "' attribute.\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400121 } else { // bit is not set
srs56949ddc14b2010-08-22 22:44:42 -0400122 attributes |= bitValue; // so set it
srs5694fed16d02010-01-27 23:03:40 -0500123 cout << "Have enabled the '" << atNames[response] << "' attribute.\n";
srs5694e7b4ff92009-08-18 13:16:10 -0400124 } // if/else
125 } // if
126 } while (response != 64);
127} // Attributes::ChangeAttributes()
128
srs56949ddc14b2010-08-22 22:44:42 -0400129// Display all defined attributes on the screen (omits undefined bits).
130void Attributes::ListAttributes(void) {
131 uint32_t bitNum;
132 string tempAttr;
133
134 for (bitNum = 0; bitNum < NUM_ATR; bitNum++) {
135 tempAttr = GetAttributeName(bitNum);
136 if (tempAttr.substr(0, 15) != "Undefined bit #" )
137 cout << bitNum << ": " << Attributes::GetAttributeName(bitNum) << "\n";
138 } // for
139} // Attributes::ListAttributes
140
srs56949ddc14b2010-08-22 22:44:42 -0400141// multifaceted attributes access
142// returns true upon success, false upon failure
143bool Attributes::OperateOnAttributes(const uint32_t partNum, const string& attributeOperator, const string& attributeBits) {
144
145 // attribute access opcode
146 typedef enum {
147 ao_or, ao_nand, ao_xor, ao_assignall, // operate on all attributes (bitmask)
148 ao_unknown, // must be after bitmask operators and before bitnum operators
149 ao_set, ao_clear, ao_toggle, ao_get // operate on a single attribute (bitnum)
150 } attribute_opcode_t; // typedef enum
151
152 // translate attribute operator into an attribute opcode
153 attribute_opcode_t attributeOpcode = ao_unknown; { // opcode is not known yet
154 if (attributeOperator == "or") attributeOpcode = ao_or;
155 else if (attributeOperator == "nand") attributeOpcode = ao_nand;
156 else if (attributeOperator == "xor") attributeOpcode = ao_xor;
157 else if (attributeOperator == "=") attributeOpcode = ao_assignall;
158 else if (attributeOperator == "set") attributeOpcode = ao_set;
159 else if (attributeOperator == "clear") attributeOpcode = ao_clear;
160 else if (attributeOperator == "toggle") attributeOpcode = ao_toggle;
161 else if (attributeOperator == "get") attributeOpcode = ao_get;
162 else {
163 cerr << "Unknown attributes operator: " << attributeOperator << endl;
164 return false;
165 } // else
166 } // attributeOpcode
167
168 // get bit mask if operating on entire attribute set
169 uint64_t attributeBitMask; { if (attributeOpcode < ao_unknown) {
170 if (1 != sscanf (attributeBits.c_str(), "%qx", (long long unsigned int*) &attributeBitMask)) {
171 cerr << "Could not convert hex attribute mask" << endl;
172 return false;
173 } // if
174 }} // attributeBitMask, if
175
176 // get bit number and calculate bit mask if operating on a single attribute
177 int bitNum; { if (attributeOpcode > ao_unknown) {
178 if (1 != sscanf (attributeBits.c_str(), "%d", &bitNum)) {
179 cerr << "Could not convert bit number" << endl;
180 return false;
181 } // if
182 const uint64_t one = 1;
183 attributeBitMask = one << bitNum;
184 }} // bitNum, if
185
186 switch (attributeOpcode) {
187 // assign all attributes at once
188 case ao_assignall: attributes = attributeBitMask; break;
189
190 // set individual attribute(s)
191 case ao_set:
192 case ao_or: attributes |= attributeBitMask; break;
193
194 // clear individual attribute(s)
195 case ao_clear:
196 case ao_nand: attributes &= ~attributeBitMask; break;
197
198 // toggle individual attribute(s)
199 case ao_toggle:
200 case ao_xor: attributes ^= attributeBitMask; break;
201
202 // display a single attribute
203 case ao_get: {
srs5694ab4b0432010-09-25 20:39:52 -0400204 cout << partNum+1 << ":" << bitNum << ":"
205 << bool (attributeBitMask & attributes) << endl;
srs56949ddc14b2010-08-22 22:44:42 -0400206 break;
207 } // case ao_get
208
209 default: break; // will never get here
210 } // switch
211
212 return true;
213} // Attributes::OperateOnAttributes()
srs56940873e9d2010-10-07 13:00:45 -0400214
215/*******************************
216* *
217* Non-class support functions *
218* *
219*******************************/
220
221// Display attributes
222ostream & operator<<(ostream & os, const Attributes & data) {
223 os << data.GetAttributes();
224 return os;
225} // operator<<()